home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / lkbackup.zip / mttape.c < prev    next >
C/C++ Source or Header  |  1993-11-03  |  98KB  |  3,426 lines

  1. /*
  2.  
  3.  The following is my version of a tape backup program for windows nt
  4.  
  5. It was written because ntbackup fails on my gigatrend 1200 data drive, but
  6. the driver I wrote for it passes the hardware compat. test fine.
  7.  
  8. The software allows you to backup/restore savesets to tape (50 savesets max).
  9. It also allows you to list the tape/and or saveset contents and backup/restore
  10. by wildcard ie *dirname* etc. I have implemented compression utilizing a
  11. modified version of gnu zip but on my dat even with a 100K threshold for
  12. zip it takes long and more tape so the compression by default is
  13. disabled unless you specify the -c option.  for a list of options run lkbackup -h
  14.  
  15. The tape drive used by the backup program must have an nt driver and
  16. support the following functions: 
  17.  
  18. 1. Writefile/readfile for reading writing to tape
  19.  
  20. 2. it must be device tape0 (ie the first tape device in the system although
  21. this can be changed in the source code)
  22.  
  23. 3. it must support either filemarks or setmarks (default is filemarks
  24. use -s option for setmarks).
  25.  
  26. 4. it must support spacing to end of data and filemark/setmark +/-
  27. spacing
  28.  
  29. 5. it must support scsi data block aka relative blocking/spacing (it
  30. doesn't use absolute or logical blocking).
  31.  
  32. 6. it must support the load/unload/rewind tape apis in win32.
  33.  
  34. 7. You must have your temp variable set since this is where the
  35. zipped/unzipped files are temporarily kept, and there must be enouge space for the
  36. largest of your files (and about 30 of them if using compression).
  37.  
  38.  
  39. The program is multi-threaded in that one thread tries to compress ahead of
  40. the thread writting to tape up to 30 files.  This improved performance but
  41. uncompressed still works better on my drive.  Try it and let me know your
  42. results.  Anyway I have left the multi-threading in since with faster machines
  43. or multi-processor machines in the future it will improve perforamce.
  44.  
  45. The source code is also provided and can be used and modified provided
  46. you send me the modified code with a note about what you are doing. 
  47. Also the code cannot be used in a for sale produce without first contacting
  48. me for permission.
  49.  
  50. Good luck
  51.  
  52. Larry Kahn 10/27/93
  53. [71534.600] on compuserve
  54. Kahn@drcvax.af.mil on internet
  55. 919-630-0412 by phone
  56. 919-630-0722 by fax when nt finally gets fax support
  57.  
  58. */
  59.  
  60. #include <windows.h>
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <io.h>
  64. #include <time.h>
  65. #include <process.h>
  66. #include <string.h>
  67. #include <direct.h>
  68. #include <errno.h>
  69.  
  70. /* these are the tape functions for my dat drive */
  71.  /* lgk use the modified gnu zip compression routines were modifed to provide c level interface
  72.  so that we dont need to overhead of a system call */
  73.                     
  74.  struct _TAPE_SET_MEDIA_PARAMETERS tparms;
  75.  
  76.  
  77.  #define max_save_sets 50
  78.  #define save_sets_per_block 10
  79.  #define blocks_per_header 5
  80.  #define bsize1 4096
  81.  const int blocksize = bsize1;
  82.  DWORD buffersize = bsize1;
  83.  const int headersize = 2048;
  84.  char saveset_buffer[2049];
  85.  BOOLEAN debug = FALSE;
  86.  int save_sets_on_tape = 0;
  87.  static char backup_version[13] = "LGKBACKUP1.0\0";
  88.  unsigned int total_original_size;
  89.  unsigned int total_backup_size;
  90.  int current_tape_block_number = 0;
  91.  BOOLEAN want_compression = TRUE;
  92.  volatile int filescompressed = 0;
  93.  volatile int filesuncompressed = 0;
  94.  DWORD start_time;
  95.  
  96.  typedef  struct savesettag {
  97.             char filename[300];
  98.             unsigned int filesize; /* suports 4 gif */
  99.             unsigned int starting_datablock_number;
  100.            } SAVESET_HEADER;
  101.            
  102.  SAVESET_HEADER my_saveset_header;
  103.  
  104.  
  105.  
  106. /* 11 per buffer use 4 buffers */
  107.  
  108.  typedef struct tapeheadertag {
  109.                   char saveset_name[18];
  110.                   unsigned int original_size;
  111.                   unsigned int compressed_size;
  112.                   char date[9];
  113.                   } TAPE_HEADER;
  114.                   
  115.   TAPE_HEADER my_tape_header;
  116.  
  117.   typedef struct rawtag {
  118.             char backupversion[13];
  119.             TAPE_HEADER header[max_save_sets];
  120.             } RAW_TAPE_HEADERT;
  121.  
  122. /* 15 save sets means we only need the first 512 byte block
  123.  since each reacord needs 32 bytes plus the first 12 = 502 total */
  124.  
  125.  
  126.  RAW_TAPE_HEADERT raw_tape_header;
  127.     
  128.     typedef struct indexrectag {
  129.                   int original_size;
  130.                  int compressed_size;
  131.                  char fname[351];
  132.                  int start_block;
  133.                  char date[9];
  134.                     } INDEX_REC_TYPE;
  135.   
  136.  
  137.  const int header_size = sizeof(raw_tape_header);
  138.   
  139.  extern int gzip_compress(char *,char *);
  140.  extern int gzip_decompress(char *,char *);
  141.   
  142.   FILE *TempIndexFile;
  143.   char TempIndexFileName[MAX_PATH];
  144.   BOOLEAN tempindexfileopen = FALSE; 
  145.   HANDLE hTape;   /* handle to tape device */
  146.   DWORD  dwBytesRead, dwBytesWritten, dwPos;
  147.   BOOLEAN rdflag, wrflag;
  148.   BOOLEAN tape_opened = FALSE;
  149.   char todays_date[9];
  150.   unsigned int total_bytes_read = 0;
  151.   BOOLEAN quiet_mode = FALSE;
  152.   BOOLEAN set_mark_positioning = FALSE;
  153.   BOOLEAN reading_header = FALSE;
  154.   volatile int filesskipped = 0;
  155.   CRITICAL_SECTION Protected_Element;
  156.   CRITICAL_SECTION Protected_Queue;
  157.   BOOLEAN file_mapping = TRUE; 
  158.   const DWORD compress_threshold = 100000;
  159.   /* turn off compression if file > than threshold size */
  160.  
  161.   typedef struct readqueuetag {
  162.          char original_filename[400];
  163.          char temp_filename[100];
  164.          int  size;
  165.          BOOLEAN compressed;
  166.          DWORD attrs;
  167.          DWORD lowdate;
  168.          DWORD highdate;
  169.                             } READ_QUEUE_TYPE;
  170.  
  171.  READ_QUEUE_TYPE read_queue[31];
  172.  volatile int elements_in_queue = 0;
  173.  volatile int current_queue_pop_item = 0;
  174.  volatile int current_queue_push_item = 0;
  175.  const int queue_size = 30;
  176.  volatile BOOLEAN processed_all_files = FALSE;
  177.  char Global_SearchString[100];
  178.  volatile BOOLEAN global_process_subdirs = FALSE;
  179.  BOOLEAN debug_child = FALSE;
  180.  volatile BOOLEAN thread_active = FALSE;
  181.  HANDLE hThread;
  182.  
  183.  
  184. #define severe 1
  185. #define warning 0
  186.  
  187. /* ------------------------------------------------------------------------------------ */
  188. /* beginning of functions */
  189. /* ------------------------------------------------------------------------------------------- */
  190.  
  191.  int read_elements_in_queue()
  192.    {
  193.  
  194.      int rvalue;
  195.      EnterCriticalSection(&Protected_Element);
  196.      rvalue = elements_in_queue;
  197.      LeaveCriticalSection(&Protected_Element);
  198.      return(rvalue);
  199.     }
  200.  
  201.   /* ------------------------------------------------------------------------------------------- */
  202.  
  203.  void increment_elements_in_queue()
  204.    {
  205.     EnterCriticalSection(&Protected_Element);
  206.     ++elements_in_queue;
  207.     LeaveCriticalSection(&Protected_Element);
  208.    }
  209.  
  210.  /* ------------------------------------------------------------------------------------------- */
  211.  
  212.  void decrement_elements_in_queue()
  213.    {
  214.     EnterCriticalSection(&Protected_Element);
  215.      --elements_in_queue;
  216.     LeaveCriticalSection(&Protected_Element);
  217.     }
  218.  
  219.  /* ------------------------------------------------------------------------------------------- */
  220.  
  221.  void push_element(element)
  222.    READ_QUEUE_TYPE element;
  223.     {
  224.      EnterCriticalSection(&Protected_Queue);
  225.      strcpy(read_queue[current_queue_push_item].original_filename,element.original_filename);
  226.      strcpy(read_queue[current_queue_push_item].temp_filename,element.temp_filename);
  227.      read_queue[current_queue_push_item].size = element.size;
  228.      read_queue[current_queue_push_item].attrs = element.attrs;
  229.      read_queue[current_queue_push_item].lowdate = element.lowdate;
  230.      read_queue[current_queue_push_item].highdate = element.highdate;
  231.      read_queue[current_queue_push_item].compressed = element.compressed;
  232.      
  233.      ++current_queue_push_item;
  234.      if (current_queue_push_item > 29)
  235.        current_queue_push_item = 0;
  236.      LeaveCriticalSection(&Protected_Queue);
  237.      increment_elements_in_queue();
  238.     }
  239.  
  240.  /* ------------------------------------------------------------------------------------------- */
  241.  
  242.   READ_QUEUE_TYPE pop_element()
  243.    {
  244.      
  245.      READ_QUEUE_TYPE element;
  246.  
  247.      EnterCriticalSection(&Protected_Queue);
  248.      strcpy(element.original_filename,read_queue[current_queue_pop_item].original_filename);
  249.      strcpy(element.temp_filename,read_queue[current_queue_pop_item].temp_filename);
  250.      element.size = read_queue[current_queue_pop_item].size;
  251.      element.attrs = read_queue[current_queue_pop_item].attrs;
  252.      element.lowdate = read_queue[current_queue_pop_item].lowdate;
  253.      element.highdate = read_queue[current_queue_pop_item].highdate;
  254.      element.compressed = read_queue[current_queue_pop_item].compressed;
  255.      
  256.      ++current_queue_pop_item;
  257.      if (current_queue_pop_item > 29)
  258.        current_queue_pop_item = 0;
  259.      LeaveCriticalSection(&Protected_Queue);
  260.      decrement_elements_in_queue();
  261.  
  262.      return(element);
  263.    }
  264.  
  265.  
  266.   /* ------------------------------------------------------------------------------------------- */
  267.  
  268.    /* recursive wild card search routine */
  269.  
  270.    BOOLEAN wild_match(search_string,target)
  271.      char *search_string;
  272.      char *target;
  273.  
  274.      {
  275.  
  276.       char *new_target;
  277.       int lens = strlen(search_string);
  278.       int lent = strlen(target);
  279.       BOOLEAN rvalue = FALSE;
  280.  
  281.  
  282.       /* handle terminating cases first */
  283.       if (lens == 1) /* last char of search string */
  284.         {
  285.           if (strncmp(search_string,"*",1) == 0) 
  286.             {
  287.               /* is a wild card * */
  288.               return(TRUE);
  289.             }
  290.           
  291.           else if ((strncmp(search_string,"?",1) == 0) && (lent == 1))
  292.              {
  293.                /* is a wild card ? */
  294.                return(TRUE);
  295.              }
  296.           else /* other char only matches if lent is also 1 and they match */
  297.              {
  298.                if ((lent == 1) && (strncmp(search_string,target,1) == 0))  
  299.                  return(TRUE);
  300.                else return(FALSE);
  301.              }
  302.  
  303.          } /* lens = 1 */
  304.         
  305.        else /* lens > 1 */
  306.          {
  307.            /* now check if chars is ? */
  308.            if (strncmp(search_string,"?",1) == 0)
  309.              {
  310.                /* if ? skip a char in both strings and recurse */
  311.                ++search_string;
  312.                ++target;
  313.                return(wild_match(search_string,target));
  314.              }
  315.               /* now check if char is * */
  316.             if (strncmp(search_string,"*",1) == 0)
  317.               {
  318.                      /* find next char in search string  */
  319.                      do
  320.                         {
  321.                          ++search_string;       
  322.                            /* here we also need to skip over ? as long as there is a char left
  323.                              in the target */
  324.                               
  325.                         } while (((strncmp(search_string,"*",1) == 0) || 
  326.                                   ((strncmp(search_string,"?",1) == 0)) && (lent >= 1)));
  327.                        /* if it is a ? recurse */
  328.                       
  329.                       if ((strncmp(search_string,"?",1) == 0) && (lent == 0))
  330.                          return(FALSE);
  331.  
  332.                        else /* other ok character no we need to find this character in the
  333.                               target and recurse to try and resolve if the recursion fails
  334.                               we need to try further on in the string do this until we either
  335.                               suceed or the target string runs out and we fail */
  336.                          {
  337.  
  338.                            rvalue = FALSE;
  339.                            new_target = search_string;
  340.                           do
  341.                             {
  342.                               new_target = strchr(target,new_target[0]);
  343.                               if (new_target == NULL)
  344.                                 {
  345.                                  /* couldn't find character so we fail */
  346.                                  return(FALSE);
  347.                                 }
  348.                                else
  349.                                  {
  350.                                   /* found the char so recurse with it */
  351.                                   rvalue = wild_match(search_string,new_target);
  352.                                  }
  353.                                  /* increment here */
  354.                                  target = new_target;
  355.                                   if (strlen(target) == 1)
  356.                                     return(FALSE);
  357.                                   else ++target;
  358.                                } while (rvalue == FALSE);
  359.                                
  360.                               /* if we get out of the inner loop without returning it means
  361.                                we found a successfull match so we can return it */
  362.                                return(rvalue);
  363.                     } /* end of not * or ? */
  364.  
  365.                } /* end of srch string was * */
  366.  
  367.             else
  368.                {
  369.                  /* srch string is another character so find it in target */
  370.                  /* if next char in target is not the search string then we fail here
  371.                     otherwise we need to increment both and recurse */
  372.                  /* we also have a terminating case if if the length of the search string
  373.                     is greater than one and the length of the remaining target string is only
  374.                     one since the search string here is not a wildcard */
  375.                   if (lent <= 1) 
  376.                     return(FALSE);
  377.  
  378.                   else if (strncmp(search_string,target,1) != 0)
  379.                      return(FALSE);
  380.                   else 
  381.                      { /* they are equal so recurse through remainder of the string */
  382.                       ++search_string;
  383.                       ++target;
  384.                       return(wild_match(search_string,target));
  385.                      }
  386.                   } /* end search string is regular character case */
  387.  
  388.             } /* end len of srch string > 1 */           
  389.   } /* end of routine */
  390.  
  391.   /* -------------------------------------------------------------------------------------- */
  392.  
  393. void store_start_time()
  394.    {
  395.      start_time = GetTickCount();
  396.    }
  397.  
  398.  /* ----------------------------------------------------------------------------------------- */
  399.  void close_tape()
  400.    {
  401.       CloseHandle(hTape);
  402.       if (debug)
  403.         {
  404.           printf("TapeIO:--> Closed Tape Drive\n\n");
  405.           fflush(stdout);
  406.         }
  407.     tape_opened = FALSE;
  408.     }
  409.  
  410.  /* -------------------------------------------------------------------------------------------     */
  411.  
  412.  void terminate_program()
  413.  
  414.   {
  415.     if (tape_opened)
  416.          close_tape();
  417.          /* attempt to close the thread handle */
  418.     if (thread_active)
  419.            CloseHandle(hThread);
  420.  
  421.     exit(1);
  422. }
  423.  
  424.  /* ------------------------------------------------------------------------------------ */
  425.  
  426.  void mt_terminate_program()
  427.  
  428.   {
  429.     if (tape_opened)
  430.         close_tape();
  431.          
  432.     ExitThread(1);
  433. }
  434.  
  435.  /* ------------------------------------------------------------------------------------ */
  436.     /* routine to report an error and terminat if severe */
  437.  
  438.  void report_error(text,rvalue,severity)
  439.    char text[20];
  440.    DWORD rvalue;
  441.    int severity;
  442.    {
  443.      printf("TapeIO: --> Error %s :",text);
  444.  
  445.      if (rvalue > 0) 
  446.         printf(" error code returned = %ld ",rvalue);
  447.         
  448.      printf(" Severity = %d \n",severity);
  449.      fflush(stdout);
  450.      
  451.      if (severity > 0)
  452.        terminate_program();
  453.       
  454.     }
  455.   /* --------------------------------------------------------------------------------------- */
  456.  
  457.     /* routine to report an error and terminat if severe */
  458.        /* multi threaded version for correct thread cleanup called if thread fails */
  459.  
  460.  void mt_report_error(text,rvalue,severity)
  461.    char text[20];
  462.    DWORD rvalue;
  463.    int severity;
  464.    {
  465.      printf("TapeIO: --> Error %s :",text);
  466.  
  467.      if (rvalue > 0) 
  468.         printf(" error code returned = %ld ",rvalue);
  469.         
  470.      printf(" Severity = %d \n",severity);
  471.      fflush(stdout);
  472.      
  473.      if (severity > 0)
  474.        mt_terminate_program();
  475.       
  476.     }
  477.   /* --------------------------------------------------------------------------------------- */
  478.  
  479.  /*
  480.  * After a file/link/symlink/dir creation has failed, see if
  481.  * it's because some required directory was not present, and if
  482.  * so, create all required dirs.
  483.  */
  484. int
  485. make_dirs (pathname)
  486.      char *pathname;
  487. {
  488.   char *p;            /* Points into path */
  489.   int madeone = 0;        /* Did we do anything yet? */
  490.   int save_errno = errno;    /* Remember caller's errno */
  491.   int check;
  492.  
  493.  // if (errno != ENOENT)
  494.  //   return 0;            /* Not our problem */
  495.  
  496.   for (p = strchr (pathname, '\\'); p != NULL; p = strchr (p + 1, '\\'))
  497.     {
  498.       /* Avoid mkdir of empty string, if leading or double '/' */
  499.       if (p == pathname || p[-1] == '/')
  500.     continue;
  501.       /* Avoid mkdir where last part of path is '.' */
  502.       if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
  503.     continue;
  504.       *p = 0;            /* Truncate the path there */
  505.       check = _mkdir (pathname);    /* Try to create it as a dir */
  506.             if (check == 0)
  507.     {
  508.       
  509.       if (debug)
  510.          {
  511.           printf("made directory %s \n",pathname);
  512.           fflush(stdout);
  513.          }
  514.  
  515.       madeone++;        /* Remember if we made one */
  516.       *p = '/';
  517.       continue;
  518.     }
  519.       *p = '/';
  520.       if (errno == EEXIST)    /* Directory already exists */
  521.     continue;
  522.       /*
  523.          * Some other error in the mkdir.  We return to the caller.
  524.          */
  525.       break;
  526.     }
  527.  
  528.   errno = save_errno;        /* Restore caller's errno */
  529.   return madeone;        /* Tell them to retry if we made one */
  530. }
  531.      
  532. /* --------------------------------------------------------------------------------------- */
  533.  
  534.   HANDLE open_file_for_write(filename)
  535.     char filename[360];
  536.    {
  537.  
  538.        HANDLE hFile;
  539.        int dirsmade;    
  540.  
  541.      hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
  542.         CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
  543.  
  544.  
  545.   if (hFile == INVALID_HANDLE_VALUE)
  546.     {
  547.       
  548.       /* if we fail here assume it is because the path is not there and call our function to
  549.          create directories along the path */
  550.          /* if it fails after this we are out of luck */
  551.          
  552.         if (debug)
  553.           {
  554.             printf("create file %s failed calling make dirs to create any missing directories \n",
  555.                     filename);
  556.             fflush(stdout);
  557.            }
  558.          dirsmade = make_dirs(filename);
  559.          /* now try again to open it */
  560.           
  561.          hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
  562.              CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
  563.          
  564.           if (hFile == INVALID_HANDLE_VALUE)
  565.             {
  566.              printf("TapeIO:--> Error Could not create file %s num dirs created = %d\n",
  567.                    filename,dirsmade);
  568.              report_error(" ",0,severe);   /* process error */
  569.             }
  570.  
  571.           else {
  572.                  if (debug)
  573.                    {
  574.                     printf("TapeIO:-->Created file %s \n",filename);
  575.                     fflush(stdout);
  576.                    }
  577.  
  578.                  return hFile;
  579.                 }
  580.        } /* end of first create failed */
  581.     else {
  582.           if (debug)
  583.             {
  584.              printf("TapeIO:-->Created file %s \n",filename);
  585.              fflush(stdout);
  586.              }
  587.  
  588.           return hFile;
  589.         }
  590.  }        
  591.  
  592. /* ------------------------------------------------------------------------------------ */
  593.   HANDLE open_file_for_set_time(filename)
  594.     char filename[360];
  595.      {
  596.  
  597.        HANDLE hFile;
  598.  
  599.      hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
  600.         OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
  601.  
  602.  
  603.   if (hFile == INVALID_HANDLE_VALUE)
  604.     {
  605.       
  606.       if (debug)
  607.         {
  608.           printf("TapeIO:--> Open file for set time failed error code = %d \n",GetLastError());
  609.           fflush(stdout);
  610.           return(NULL);
  611.         }
  612.      }
  613.     else return hFile;
  614.  }        
  615.  
  616. /* ------------------------------------------------------------------------------------ */
  617.    
  618.   int compress_file(filename,temppath)
  619.          char filename[];
  620.          char *temppath;
  621.     {
  622.        char TempFileName[30];
  623.           DWORD lcopied = 0;
  624.        int rvalue = 0;
  625.        char *nameloc;
  626.  
  627.       /* get the temp path */
  628.       /* append the temp filename and call gzip to execute and write the temp file name */
  629.       /* pass back the compressed file and we will back that up and remove it */
  630.     
  631.        lcopied = GetTempPath(100,temppath);
  632.        if (lcopied <= 0)
  633.           {
  634.            report_error(" Cannot retrieve temporary directory path \n",0,warning);
  635.               return(-1);
  636.           }
  637.        else
  638.          {
  639.            /* now create a temp name and concat path to name */
  640.              rvalue = GetTempFileName(temppath, /* dir. for temp. files            */
  641.                "NEW",                /* temp. filename prefix           */
  642.                  0,                    /* create unique name w/ sys. time */
  643.              (LPTSTR) TempFileName); /* buffer for name                 */
  644.  
  645.            if (rvalue == 0)
  646.              {
  647.                report_error(" Getting temp file name for compression \n",GetLastError(),warning);
  648.                  return(-1);
  649.              }
  650.            else 
  651.                {
  652.                 /* concat path to name */
  653.                 /* we only need to name form the temp file as it appends \temp\ to it
  654.                    and we already have the temppath */
  655.                   nameloc = strrchr(TempFileName,'\\');
  656.                   /* skip over slash */
  657.                   ++nameloc;
  658.  
  659.                   strcat(temppath,nameloc);
  660.                 
  661.                 if (debug)
  662.                   {
  663.                     printf("temp file for compress = %s \n",temppath);
  664.                     fflush(stdout);
  665.                   }
  666.    
  667.                    /* now create command to run zip having output go to tempfile. */
  668.     
  669.                //strcpy(cmd, "gzip -c1n ");  /* use "gzip -c" for zwrite */
  670.                //strncat(cmd, filename, sizeof(cmd)-strlen(cmd));
  671.                //strcat(cmd," > ");
  672.                //strcat(cmd, temppath);
  673.                //if (debug)
  674.                 // {
  675.                //   printf("command for gzip = %s \n",cmd);
  676.                 //   fflush(stdout);
  677.                 // }
  678.                         
  679.                 rvalue = gzip_compress(filename,temppath);
  680.  
  681.                 if (rvalue != 0)
  682.                   {
  683.                    mt_report_error("Call to execute compression failed ",rvalue,severe);
  684.                    return(-1);
  685.                   }
  686.                 else return(0);
  687.  
  688.                } /* ok temp name */
  689.             } /* ok temp path name */
  690.       }
  691.  
  692.  
  693.  /* ------------------------------------------------------------------------------------ */
  694.   
  695.   int decompress_file(filename,temppath)
  696.          char filename[];
  697.          char temppath[];
  698.     {
  699.        int rvalue = 0;
  700.       HANDLE tHandle;
  701.  
  702.            /* open the file to make sure it can be created or force creation of paths */
  703.         tHandle = open_file_for_write(filename);
  704.         CloseHandle(tHandle);
  705.     
  706.         /* now create command to run zip having output go from tempfile to original file */
  707.     
  708.         
  709.                //strcpy(cmd, "gzip -d < ");  /* use "gzip -c" for zwrite */
  710.                //strncat(cmd, temppath, sizeof(cmd)-strlen(cmd));
  711.                //strcat(cmd," > ");
  712.                //strcat(cmd, filename);
  713.                //if (debug)
  714.                 // {
  715.                 //   printf("command for gzip = %s \n",cmd);
  716.                 //   fflush(stdout);
  717.                 // }
  718.                 
  719.                 rvalue = gzip_decompress(temppath,filename);
  720.                 return(rvalue);
  721.  
  722.    }
  723.    /* ------------------------------------------------------------------------------------ */
  724.      void write_setmarks(no_marks)
  725.       DWORD no_marks; 
  726.       {
  727.         DWORD rvalue;
  728.         
  729.         if (debug)
  730.           {
  731.             printf("Attempting to Write %d setmarks \n",no_marks);
  732.             fflush(stdout);
  733.           }
  734.        
  735.         rvalue = WriteTapemark(hTape, TAPE_SETMARKS,no_marks,FALSE);
  736.  
  737.           if (rvalue != NO_ERROR)
  738.             report_error(" Tape write setmarks error ",rvalue,severe);
  739.          
  740.       }
  741.     
  742.  
  743. /* ------------------------------------------------------------------------------------ */
  744.      void write_filemarks(no_marks)
  745.       DWORD no_marks; 
  746.       {
  747.         DWORD rvalue;
  748.         
  749.         if (set_mark_positioning)
  750.           {
  751.            write_setmarks(no_marks);
  752.           }
  753.         else
  754.           {
  755.         if (debug)
  756.           {
  757.             printf("Attempting to Write %d filemarks \n",no_marks);
  758.             fflush(stdout);
  759.           }
  760.        
  761.         rvalue = WriteTapemark(hTape, TAPE_FILEMARKS,no_marks,FALSE);
  762.  
  763.           if (rvalue != NO_ERROR)
  764.             report_error(" Tape write filemarks error ",rvalue,severe);
  765.         } 
  766.       }
  767.     
  768.  
  769.  /* ------------------------------------------------------------------------------------ */
  770. void fill_in_todays_date()
  771.  
  772.   {         
  773.  
  774.    struct tm *newtime;
  775.    long ltime;
  776.  
  777.    time( <ime );
  778.  
  779.    /* Obtain Universal Coordinated Time: */
  780.    newtime = gmtime( <ime );
  781.    /* now fill in our date string */
  782.    sprintf(todays_date,"%2d-%2d-%2d",(newtime->tm_mon)+1,newtime->tm_mday,newtime->tm_year);
  783.     if (debug)
  784.       {
  785.         printf("filled in todays date with %s \n",todays_date);
  786.         fflush(stdout);
  787.       }
  788.  }
  789.  
  790.   /* ------------------------------------------------------------------------------------ */
  791.  
  792. /* routine to open up the tape drive  assumes only 1 tape drive  for now */
  793.  
  794.  void open_tape() 
  795.  
  796.   {
  797.       if (tape_opened == FALSE)
  798.         {
  799.  
  800.       hTape = CreateFile(
  801.            "\\\\.\\TAPE0",     /* name of tape device to open */
  802.            GENERIC_READ | GENERIC_WRITE, /* read-write access */
  803.            0,                    /* not used                  */
  804.            0,                    /* not used                  */
  805.            OPEN_EXISTING,        /* required for tape devices */
  806.            0,                    /* not used                  */
  807.            NULL);                /* not used                  */
  808.  
  809.  
  810.             if (hTape == NULL)
  811.                {
  812.                 report_error("Opening tape device \n",0,1);
  813.                }
  814.              else
  815.                   {
  816.                     if (debug) 
  817.                       { printf("TapeIO:--> Opened Tape drive.\n");
  818.                        fflush(stdout);
  819.                      }
  820.                     tape_opened = TRUE;
  821.                  }
  822.  
  823.             }
  824.     }
  825.  
  826.   /* ------------------------------------------------------------------------------------ */
  827.  
  828.  /* function to set block size */
  829.  
  830. void set_block_size(bsize)
  831.      unsigned long bsize;
  832.   {
  833.  
  834.     DWORD rvalue;
  835.      
  836.     tparms.BlockSize = bsize;
  837.     rvalue = SetTapeParameters(hTape,SET_TAPE_MEDIA_INFORMATION,&tparms);
  838.     if (rvalue != NO_ERROR)
  839.        {
  840.          report_error("Setting tape media information ",rvalue,severe);
  841.        }
  842.     else
  843.        {
  844.          if (debug)
  845.             {
  846.              printf("TapeIO:--> Set tape media parameters i.e. blocksize to %ld\n",bsize);
  847.              fflush(stdout);
  848.             }
  849.        }
  850.     }
  851.  
  852.  /* ------------------------------------------------------------------------------------ */
  853.  
  854.  /* rewind the tape always wait for resute no immediate mode */
  855.  
  856.  void rewind_tape(immediate)
  857.    BOOLEAN immediate;
  858.  {
  859.       DWORD rvalue;
  860.  
  861.        rvalue = PrepareTape(hTape,TAPE_LOAD,immediate);
  862.     
  863.      if ((!immediate) && (rvalue != NO_ERROR))
  864.         {
  865.            report_error("rewinding tape ",rvalue,1);
  866.         }
  867.     else
  868.         {
  869.           current_tape_block_number = 0;
  870.           if (debug)
  871.             {
  872.               printf("TapeIO:-->Rewound Tape mode = %d\n",immediate);
  873.               fflush(stdout);
  874.              }
  875.           }
  876.   }
  877.  
  878.   /* ------------------------------------------------------------------------------------ */
  879.  void space_setmarks(no_marks)
  880.      DWORD no_marks;
  881.    {
  882.      DWORD rvalue;
  883.      DWORD status;
  884.      DWORD rvalue2;
  885.      
  886.      if (debug)
  887.        {
  888.         printf("Attempting to Space %d setmarks\n",no_marks);
  889.         fflush(stdout);
  890.        }
  891.     
  892.           rvalue = SetTapePosition(hTape,TAPE_SPACE_SETMARKS,0,no_marks,0,FALSE); 
  893.           if (rvalue != NO_ERROR)
  894.              {
  895.                rvalue2 = GetLastError();
  896.                status = GetTapeStatus(hTape);
  897.                printf(" Tape positioning by setmarks error rvalue = %d tape status =%d getlsterror = %d\n",
  898.                         rvalue,status,rvalue2);
  899.                fflush(stdout);
  900.                report_error(" ",0,severe);
  901.              }
  902.         
  903.     } 
  904.  
  905. /* ------------------------------------------------------------------------------------ */
  906.  void space_filemarks(no_marks)
  907.      DWORD no_marks;
  908.    {
  909.      DWORD rvalue;
  910.      DWORD status;
  911.      DWORD rvalue2;
  912.      
  913.      if (set_mark_positioning)
  914.        {
  915.         space_setmarks(no_marks);
  916.        }
  917.      else {
  918.      if (debug)
  919.        {
  920.         printf("Attempting to Space %d file marks\n",no_marks);
  921.         fflush(stdout);
  922.        }
  923.     
  924.           rvalue = SetTapePosition(hTape,TAPE_SPACE_FILEMARKS,0,no_marks,0,FALSE); 
  925.           if (rvalue != NO_ERROR)
  926.              {
  927.                rvalue2 = GetLastError();
  928.                status = GetTapeStatus(hTape);
  929.                printf(" Tape positioning by filemarks error rvalue = %d tape status =%d getlsterror = %d\n",
  930.                         rvalue,status,rvalue2);
  931.                fflush(stdout);
  932.                report_error(" ",0,severe);
  933.              }
  934.         }
  935.     } 
  936.  
  937. /*   ---------------------------------------------------------------------------------- */
  938.  
  939.   void read_tape_block(buff)
  940.     char *buff;
  941.  
  942.     {
  943.       DWORD rdflag;
  944.  
  945.        rdflag = ReadFile(hTape, (LPSTR) buff, buffersize, &dwBytesRead, NULL);
  946.             
  947.             /* handle strange error case of not spacing over file mark correctly if on 
  948.             top of on assume it didn't space write and space over it */
  949.        if (rdflag != TRUE)
  950.          {
  951.           
  952.              if ((reading_header) && (GetLastError() == ERROR_NO_DATA_DETECTED))
  953.                { /* tape is not initialized */
  954.                  printf("ERROR while trying to read the tape header information, \n");
  955.                  printf("      no data was detected.  It appears that this tape     \n");
  956.                  printf("      has not been initialized (LKBACKUP -i) \n");
  957.                  fflush(stdout);
  958.                  report_error("Error reading tape",rdflag,severe);
  959.                }
  960.               else
  961.                 {
  962.                  printf("error reading block getlasterror %d getstatus %d \n",
  963.                          GetLastError(),GetTapeStatus(hTape));
  964.                  fflush(stdout);
  965.                  report_error("Error reading tape",0,severe);
  966.                 }
  967.              }    
  968.         else
  969.           {
  970.            ++current_tape_block_number;
  971.             if (debug)
  972.               {
  973.                 printf("TapeIO:--> Read %ld characters from the tape \n",dwBytesRead);
  974.                 fflush(stdout);
  975.               }
  976.            }
  977.     }
  978.  
  979.  /* ------------------------------------------------------------------------------------ */
  980.  
  981.     void write_tape_block(buff)
  982.     char buff[];
  983.  
  984.     {
  985.       DWORD wrflag;
  986.       DWORD dwBytesWritten;
  987.       
  988.         
  989.        wrflag = WriteFile(hTape, (LPSTR) buff, buffersize, &dwBytesWritten, NULL);
  990.        if (wrflag != TRUE)
  991.          {
  992.            report_error("Error writing tape",0,warning);
  993.          }
  994.         else
  995.           {
  996.             
  997.             if (debug)
  998.               {
  999.                 printf("TapeIO:--> Wrote %ld characters to the tape block = %d\n",
  1000.                  dwBytesWritten,current_tape_block_number);
  1001.                 fflush(stdout);
  1002.               }
  1003.             ++current_tape_block_number;
  1004.            }
  1005.     }
  1006.             
  1007.  /* -------------------------------------------------------------------------------- */
  1008.  
  1009.   DWORD read_file_block(lhfile,buff)
  1010.      
  1011.      HANDLE lhfile;
  1012.      char *buff;
  1013.  
  1014.     {
  1015.       DWORD rdflag;
  1016.       DWORD dwBytesRead = 0;
  1017.  
  1018.        rdflag = ReadFile(lhfile, (LPSTR) buff, buffersize, &dwBytesRead, NULL);
  1019.        if (rdflag != TRUE)
  1020.          {
  1021.            report_error("Error reading file",0,warning);
  1022.          }
  1023.         else
  1024.           {
  1025.             if (debug)
  1026.               {
  1027.                 printf("TapeIO:--> Read %ld characters from file \n",dwBytesRead);
  1028.                 fflush(stdout);
  1029.               }
  1030.            }
  1031.  
  1032.     return(dwBytesRead);
  1033.     }
  1034.  
  1035.  /* ------------------------------------------------------------------------------------ */
  1036.  
  1037.     DWORD write_file_block(lhfile,buff,bytes)
  1038.      
  1039.      HANDLE lhfile;
  1040.      char *buff;
  1041.      int bytes;
  1042.  
  1043.     {
  1044.       DWORD dwBytesWritten = 0;
  1045.       DWORD wrflag;
  1046.  
  1047.        wrflag = WriteFile(lhfile, (LPSTR) buff, (DWORD)bytes, &dwBytesWritten, NULL);
  1048.        if (wrflag != TRUE)
  1049.          {
  1050.            report_error("Error writing file",0,warning);
  1051.          }
  1052.         else
  1053.           {
  1054.             if (debug)
  1055.               {
  1056.                 printf("TapeIO:--> Wrote %ld characters to file \n",dwBytesWritten);
  1057.                 fflush(stdout);
  1058.               }
  1059.            }
  1060.      return(dwBytesWritten);
  1061.     }
  1062.             
  1063.  /* ------------------------------------------------------------------------------------ */
  1064.   
  1065.  void dump_header_element(element_number)
  1066.    int element_number;
  1067.     {
  1068.        
  1069.        if (strncmp(raw_tape_header.header[element_number].saveset_name,"EMPTY001_____",13) != 0)
  1070.          { /* ok not empty */
  1071.            printf("%-8d",element_number);
  1072.            printf("%16s",raw_tape_header.header[element_number].saveset_name);
  1073.            printf("%13d   %15d   %8s\n",
  1074.                raw_tape_header.header[element_number].original_size,
  1075.                raw_tape_header.header[element_number].compressed_size,
  1076.                raw_tape_header.header[element_number].date);
  1077.            fflush(stdout);
  1078.          }
  1079.     }   
  1080.  
  1081.  /* ------------------------------------------------------------------------------------ */
  1082.  
  1083.  void space_end_of_data()
  1084.    {
  1085.      DWORD rvalue;
  1086.      
  1087.      if (debug)
  1088.        {
  1089.         printf("Attempting to Space to end of data \n");
  1090.         fflush(stdout);
  1091.        }
  1092.     
  1093.           rvalue = SetTapePosition(hTape,TAPE_SPACE_END_OF_DATA,0,0,0,FALSE); 
  1094.           if (rvalue != NO_ERROR)
  1095.              {
  1096.                printf(" Tape positioning to end of data error rvalue = %d \n",rvalue);
  1097.                fflush(stdout);
  1098.                report_error(" ",rvalue,severe);
  1099.              }
  1100.     }
  1101.  
  1102. /* ----------------------------------------------------------------------------------------- */
  1103.  
  1104. void read_tape_index()
  1105.  
  1106.  {
  1107.  
  1108.   char block[bsize1];
  1109.   int offset = 0;
  1110.   int element_number = 0;
  1111.   int end_element_number = 0;
  1112.   int block_number = 0;
  1113.  
  1114.  
  1115.   open_tape();
  1116.   set_block_size(blocksize);
  1117.   rewind_tape(FALSE);
  1118.   save_sets_on_tape = 0;
  1119.   reading_header = TRUE;
  1120.  
  1121.   /* retrive the tape id first */
  1122.   read_tape_block(block);
  1123.   reading_header = FALSE;
  1124.   if (strncmp(block,backup_version,12) != 0)
  1125.         {
  1126.        /* tape is foreign format */
  1127.          printf("Warning tape is foreign in format.\n");
  1128.          printf("You must initialize it first with LKBACKUP -i\n");
  1129.          fflush(stdout);
  1130.          rewind_tape(TRUE);
  1131.          close_tape(); 
  1132.             exit(1);
  1133.          } 
  1134.  
  1135.    /* now get to the tape index */
  1136.    space_end_of_data();
  1137.    /* now go back one filemark to get to the beginning of the index */
  1138.    space_filemarks(-1);
  1139.    space_filemarks(1);
  1140.  
  1141.  
  1142.   /* retrieve all blocks of the tape index */
  1143.  
  1144.     current_tape_block_number = 0;
  1145.     for (block_number = 0; block_number < blocks_per_header; block_number++)
  1146.      {
  1147.        read_tape_block(block);
  1148.        offset = 0;
  1149.        if (debug)
  1150.          {
  1151.            printf("Retrieved block %d %4096s \n",block_number,block);
  1152.            fflush(stdout);
  1153.          }
  1154.  
  1155.         element_number = (block_number * save_sets_per_block);
  1156.         end_element_number = element_number + save_sets_per_block;
  1157.  
  1158.        do
  1159.         { 
  1160.          sscanf(block + offset,"%16s",raw_tape_header.header[element_number].saveset_name);
  1161.          offset = offset + 16;
  1162.           
  1163.          sscanf(block + offset,"%10ud",&raw_tape_header.header[element_number].original_size);
  1164.          offset=offset+10;
  1165.                
  1166.          sscanf(block + offset,"%10ud",&raw_tape_header.header[element_number].compressed_size);
  1167.          offset=offset+12;
  1168.          
  1169.          sscanf(block + offset,"%8s",&raw_tape_header.header[element_number].date);
  1170.          offset=offset+8;
  1171.  
  1172.          
  1173.          if (debug)
  1174.             {
  1175.              printf("Current offset = %d \n",offset);
  1176.              dump_header_element(element_number);
  1177.              }
  1178.         
  1179.          ++element_number;
  1180.          } while (element_number < end_element_number);
  1181.        
  1182.        } /* end for all blocks */
  1183.    rewind_tape(FALSE);
  1184.   }
  1185.   
  1186. /* ------------------------------------------------------------------------------------ */
  1187.  
  1188. void write_tape_id()
  1189.  
  1190.   {
  1191.   
  1192.     char block[bsize1];
  1193.     int offset;
  1194.  
  1195.     open_tape();
  1196.     set_block_size(blocksize);
  1197.     rewind_tape(FALSE);
  1198.     
  1199.     /* fill in backup version and all blocks info */
  1200.  
  1201.         offset =  sprintf(block,"%12s %8s\0",backup_version,todays_date);
  1202.         write_tape_block(block); /* force data to be written */
  1203.         write_filemarks(1);
  1204.   }
  1205.     
  1206. /* ------------------------------------------------------------------------------------- */
  1207.       
  1208. void write_tape_index(already_positioned)
  1209.   BOOLEAN already_positioned;
  1210.  
  1211.  {
  1212.  
  1213.   char block[bsize1];
  1214.   int element_number = 0;
  1215.   int end_element_number = 0;
  1216.   int offset = 0;
  1217.   int block_number = 0;
  1218.  
  1219.   if (!already_positioned)
  1220.      {
  1221.       open_tape();
  1222.       set_block_size(blocksize);
  1223.       /* space to end of tape data */
  1224.       rewind_tape(FALSE);
  1225.       space_end_of_data();
  1226.        }
  1227.  
  1228.    current_tape_block_number = 0;
  1229.    for (block_number = 0; block_number < blocks_per_header; block_number++)
  1230.      {
  1231.          offset = 0;
  1232.          for (element_number = (block_number * save_sets_per_block); element_number < (save_sets_per_block * (block_number + 1)); element_number++)
  1233.        {
  1234.          offset = offset + sprintf(block + offset,"%16s%10u %10u %8s",
  1235.                                       raw_tape_header.header[element_number].saveset_name,
  1236.                                       raw_tape_header.header[element_number].original_size,
  1237.                                       raw_tape_header.header[element_number].compressed_size,
  1238.                                       raw_tape_header.header[element_number].date);
  1239.         }
  1240.  
  1241.    if (debug)
  1242.      printf("TapeIO:--> character count in buffer = %d\n",offset);
  1243.      
  1244.     write_tape_block(block);
  1245.        
  1246.     if (debug)
  1247.       {
  1248.         printf("wrote block %d %4096s \n",block_number,block);
  1249.         fflush(stdout);
  1250.       }
  1251.  
  1252.      
  1253.     } /* end for loop */
  1254.       /* write the file mark after the index */
  1255.       rewind_tape(TRUE);
  1256.   }
  1257.   
  1258.   
  1259. /* ----------------------------------------------------------------------------- */
  1260.  
  1261.   void fill_in_header_element(name,osize,csize,date,element_number)
  1262.     char name[18];
  1263.     unsigned int osize;
  1264.     unsigned int csize;
  1265.     char date[9];
  1266.     int element_number;    
  1267.  
  1268.  
  1269.     {
  1270.            strncpy(raw_tape_header.header[element_number].saveset_name,name,16);
  1271.            raw_tape_header.header[element_number].original_size = osize;
  1272.            raw_tape_header.header[element_number].compressed_size = csize;
  1273.            strncpy(raw_tape_header.header[element_number].date,date,8);
  1274.            raw_tape_header.header[element_number].date[8] = '\0';
  1275.     
  1276.     } 
  1277.        
  1278.  
  1279.  /* ----------------------------------------------------------------------------------------- */
  1280.  
  1281.   void clear_header()
  1282.    {
  1283.  
  1284.     int element_number;
  1285.     
  1286.     for (element_number = 0; element_number< max_save_sets; element_number++)
  1287.        fill_in_header_element("EMPTY001______________________",0,0,"00-00-00",element_number);
  1288.    }   
  1289.  
  1290.  
  1291.  /* ------------------------------------------------------------------------------------------- */
  1292.   
  1293.   void initialize_tape()
  1294.    {
  1295.  
  1296.     if (debug)
  1297.        {
  1298.          printf("TapeIO:--> Initializing Tape.\n");
  1299.          fflush(stdout);
  1300.        }
  1301.     
  1302.     open_tape();
  1303.     rewind_tape(FALSE);
  1304.     write_tape_id();
  1305.  
  1306.     clear_header();
  1307.     write_tape_index(TRUE);
  1308.     
  1309.     }   
  1310.  
  1311.  
  1312.  /* ------------------------------------------------------------------------------------------- */
  1313.   
  1314.   void catalog_tape(no_good_backups)
  1315.     char *no_good_backups;
  1316.  
  1317.    {
  1318.  
  1319.     int no_backups;
  1320.     int rvalue;
  1321.     int element_number;
  1322.     char current_name[40];
  1323.     char current_number[4];
  1324.  
  1325.     rvalue = sscanf(no_good_backups,"%d",&no_backups);
  1326.     if (rvalue == 0)
  1327.       {
  1328.         printf("Error %s is not a legal integer value for the number of good backups on the tape \n",
  1329.                              no_good_backups);
  1330.         fflush(stdout);
  1331.         report_error(" ",0,severe);
  1332.       }
  1333.      /* check for legal number */
  1334.       if ((no_backups < 1) || (no_backups > max_save_sets))   
  1335.            {
  1336.             printf("Error %d is not a legal integer value for the number of good backups on the tape \n",
  1337.                              no_backups);
  1338.         fflush(stdout);
  1339.         report_error(" ",0,severe);
  1340.         }
  1341.       /* otherwise do it */
  1342.       /* fill in the correct number in the header */
  1343.       clear_header();
  1344.       for (element_number = 0; element_number < no_backups; element_number++)
  1345.          {
  1346.           strcpy(current_name,"saveset");
  1347.           sprintf(current_number,"%d",element_number+1);
  1348.           strcat(current_name,current_number);
  1349.           while (strlen(current_name) < 30)
  1350.             strcat(current_name," ");
  1351.           if (debug)
  1352.             {
  1353.               printf("Filling in header with %s for saveset name len = %d \n",current_name, 
  1354.                        strlen(current_name));
  1355.               fflush(stdout);
  1356.             } 
  1357.            fill_in_header_element(current_name,0,0,"00-00-00",element_number);
  1358.           }    /* end of loop */
  1359.          /* now space to end of data and write out the index file again */
  1360.  
  1361.           if (!quiet_mode)
  1362.           {
  1363.            printf("Attempting to restore the tape index\n");
  1364.            fflush(stdout);
  1365.           }
  1366.  
  1367.     if (debug)
  1368.        {
  1369.          printf("TapeIO:--> Initializing Tape.\n");
  1370.          fflush(stdout);
  1371.        }
  1372.     
  1373.     write_tape_index(FALSE);
  1374.     
  1375.     }   
  1376.  
  1377. /* ------------------------------------------------------------------------------------ */
  1378.  
  1379.  void erase_tape(secure)
  1380.     BOOLEAN secure;
  1381.  
  1382.     {        
  1383.  
  1384.      DWORD rvalue;
  1385.       
  1386.       open_tape();
  1387.       rewind_tape(FALSE);
  1388.  
  1389.       current_tape_block_number = 0;
  1390.       if (secure)
  1391.           rvalue = EraseTape(hTape,TAPE_ERASE_LONG,FALSE);
  1392.       else rvalue = EraseTape(hTape,TAPE_ERASE_SHORT,FALSE);
  1393.  
  1394.      if (rvalue != NO_ERROR)
  1395.         {
  1396.            report_error("Erasing tape ",rvalue,severe);
  1397.         }
  1398.  
  1399.     else
  1400.         
  1401.         {
  1402.           if (debug)
  1403.             {
  1404.               printf("TapeIO:-->Erased Tape");
  1405.               if (secure) 
  1406.                 printf(" Secure/long \n");
  1407.               else printf(" Short \n");
  1408.               fflush(stdout);
  1409.              }
  1410.         rewind_tape(TRUE);
  1411.           }
  1412.   }
  1413.  
  1414. /* ------------------------------------------------------------------------------------ */
  1415.  
  1416.   HANDLE open_file_for_read(filename,doing_backup_restore)
  1417.     char filename[200];
  1418.     BOOLEAN doing_backup_restore;
  1419.      {
  1420.  
  1421.        HANDLE hFile;    
  1422.  
  1423.      hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
  1424.  
  1425.  
  1426.   if (hFile == INVALID_HANDLE_VALUE)
  1427.     {
  1428.       printf("TapeIO:--> Error Could not open file %s\n",filename);
  1429.       fflush(stdout);
  1430.       if (doing_backup_restore)
  1431.         {
  1432.          return(NULL);
  1433.         }
  1434.        else
  1435.         report_error(" ",0,severe);   /* process error */
  1436.     }
  1437.  
  1438.    else {
  1439.           if (debug)
  1440.             {
  1441.              printf("TapeIO:-->Opened file %s \n",filename);
  1442.              fflush(stdout);
  1443.              }
  1444.  
  1445.     return hFile;
  1446.         }
  1447.  }        
  1448.  
  1449. /* --------------------------------------------------------------------------------------- */
  1450.  
  1451. void open_index_file()
  1452.   {
  1453.  
  1454.  DWORD lcopied = 0;
  1455.  int rvalue = 0;
  1456.  char TempName[40];
  1457.  char *nameloc;
  1458.  
  1459.  if (!tempindexfileopen)
  1460.    {
  1461.        lcopied = GetTempPath(100,TempIndexFileName);
  1462.        if (lcopied <= 0)
  1463.            report_error(" Cannot retrieve temporary directory path \n",0,severe);
  1464.        else
  1465.          {
  1466.            /* now create a temp name and concat path to name */
  1467.              rvalue = GetTempFileName(TempIndexFileName, /* dir. for temp. files            */
  1468.                "NEW",                /* temp. filename prefix           */
  1469.                  0,                    /* create unique name w/ sys. time */
  1470.              (LPTSTR) TempName); /* buffer for name                 */
  1471.  
  1472.            if (rvalue == 0)
  1473.                report_error(" Getting temp file name for index file \n",rvalue,severe);
  1474.            else 
  1475.                {
  1476.                 /* concat path to name */
  1477.                 /* we only need to name form the temp file as it appends \temp\ to it
  1478.                    and we already have the temppath */
  1479.                   nameloc = strrchr(TempName,'\\');
  1480.                   /* skip over slash */
  1481.                   ++nameloc;
  1482.  
  1483.                   strcat(TempIndexFileName,nameloc);
  1484.                    
  1485.              TempIndexFile = fopen(TempIndexFileName,"w");
  1486.            
  1487.                 if (TempIndexFile == NULL)
  1488.                   report_error(" Could not create temporary index file.",0,severe);
  1489.                 else 
  1490.                   {
  1491.                    if (debug)
  1492.                      {
  1493.                        printf("created temp index file %s \n",TempIndexFileName);
  1494.                        fflush(stdout);
  1495.                       }
  1496.  
  1497.                      tempindexfileopen = TRUE;
  1498.                   }
  1499.                } /* name ok */
  1500.          } /* path ok */
  1501.       } /* not already open */
  1502.    }
  1503.           
  1504. /* --------------------------------------------------------------------------------------- */
  1505. void write_index_entry(fpath,size,compressed_size,date,start_block)
  1506.    
  1507.    char fpath[512];
  1508.    unsigned int size;
  1509.    unsigned int compressed_size;
  1510.    char date[9];
  1511.    int start_block;
  1512.  
  1513.    {
  1514.      int compression_percent = (int)(100.00 * (1.000 - (float)((float)compressed_size/(float)size)));
  1515.  
  1516.          if ((compressed_size == 0) && (size > 0))
  1517.            compression_percent = 0;
  1518.  
  1519.          if (!tempindexfileopen)
  1520.            open_index_file();
  1521.  
  1522.         /* write info to command line and then to index file */
  1523.         if (!quiet_mode)
  1524.           {
  1525.            printf("%s %d %d (%d)%%  %8s %d\n",
  1526.                                     fpath,size,compressed_size,compression_percent,date,start_block);
  1527.           }
  1528.  
  1529.         fprintf(TempIndexFile,"%350s %10d %10d %8s %10d \n",
  1530.            fpath,size,compressed_size,date,start_block);
  1531.         
  1532.          fflush(stdout);
  1533.         fflush(TempIndexFile);
  1534.   }
  1535.  
  1536. /* --------------------------------------------------------------------------------------*/
  1537.  void close_index_file()
  1538.   {  
  1539.  
  1540.      if (tempindexfileopen)
  1541.        {
  1542.          fclose(TempIndexFile);
  1543.          if (debug)
  1544.            {
  1545.              printf("closed temp index file \n");
  1546.              fflush(stdout);
  1547.            }
  1548.         tempindexfileopen = FALSE;
  1549.         }
  1550.   }
  1551.  
  1552. /* --------------------------------------------------------------------------------------*/
  1553.  
  1554.  void mt_compress_file(filename,size)
  1555.     char filename[];
  1556.     DWORD size;
  1557.  
  1558.     {
  1559.       char lbuffer[bsize1];
  1560.       HANDLE hFile;
  1561.       LPTSTR ppszFilePart;    /* address of filename in path    */
  1562.       DWORD rvalue;
  1563.       FILETIME wtime;
  1564.       BOOLEAN oktime;
  1565.       DWORD dwAttrs;
  1566.       char savepath[513];
  1567.       int ldwBytesRead = 0;
  1568.       char compress_name[500];
  1569.       char fnamecopy[500];
  1570.       int queue_elements;
  1571.       READ_QUEUE_TYPE element;
  1572.       BOOLEAN compressed = FALSE;
  1573.       BOOLEAN compressed_ok = FALSE;
  1574.  
  1575.  
  1576.       strcpy(fnamecopy,lbuffer);
  1577.       hFile = open_file_for_read(filename,TRUE);
  1578.      
  1579.      if (hFile == NULL) /* skip it since it couldn't be opened */
  1580.        {
  1581.          ++filesskipped;
  1582.          printf("Warning skipping file %s which could not be opened. \n",filename);
  1583.          fflush(stdout);
  1584.        }
  1585.  
  1586.      else
  1587.  
  1588.       {
  1589.  
  1590.     if (debug_child)
  1591.       {
  1592.         printf("TapeIO:--> In child thread Attempting to compress %s size is %ld \n",filename,size);
  1593.         fflush(stdout);
  1594.       }         
  1595.        /* write full path to file */
  1596.        /* but erase first 3 chars ie i:\ so that restore is not drive specific */
  1597.  
  1598.     rvalue = GetFullPathName((LPCSTR)filename,buffersize,(LPTSTR)lbuffer,&ppszFilePart);
  1599.     if (rvalue == 0)
  1600.        {
  1601.          CloseHandle(hFile);
  1602.          printf("Warning skipping file %s because full path and filename is longer than 512 chars \n",filename);
  1603.          fflush(stdout);
  1604.          ++filesskipped;
  1605.        }
  1606.      else
  1607.        {
  1608.     
  1609.     strcpy(fnamecopy,lbuffer);
  1610.  
  1611.     lbuffer[0] = ' ';
  1612.        lbuffer[1] = ' ';
  1613.     lbuffer[2] = ' ';
  1614.  
  1615.     strcpy(savepath,lbuffer);
  1616.  
  1617.     if (debug_child)
  1618.       {
  1619.         printf("TapeIO:--> Attempting to compress %s size is %ld \n",savepath,size);
  1620.         fflush(stdout);
  1621.       }         
  1622.                    
  1623.     /* now write file date/time and attributes */
  1624.      oktime = GetFileTime(hFile,NULL,NULL,&wtime);
  1625.      if (!oktime)
  1626.        report_error(" Couldn't retrieve file time \n",0,warning);
  1627.      
  1628.      /* get attr string */
  1629.    
  1630.       dwAttrs = GetFileAttributes(filename);
  1631.       sprintf(lbuffer + rvalue," %d %d %d %d",size,dwAttrs, 
  1632.                wtime.dwLowDateTime,wtime.dwHighDateTime);
  1633.   
  1634.       CloseHandle(hFile);
  1635.       /* only compress if below threshold size to try and keep tape streaming */
  1636.       if (((size < compress_threshold) && (size > (DWORD)blocksize))  && (want_compression))
  1637.         {
  1638.           compressed = TRUE;
  1639.           rvalue = compress_file(filename,&compress_name);
  1640.           if (debug_child)
  1641.            {
  1642.             printf("rvalue from compression = %d \n",rvalue);
  1643.             fflush(stdout);
  1644.            }
  1645.  
  1646.           if (rvalue == 0)
  1647.             {
  1648.              compressed_ok = TRUE;
  1649.              /* file was compressed ok so log the stuff to the queue and go on */
  1650.               if (debug_child)
  1651.                {
  1652.                 printf("file %s compressed correctly temp name = %s\n",filename,compress_name);
  1653.                 fflush(stdout);
  1654.                } 
  1655.             
  1656.             }
  1657.           else
  1658.             {
  1659.              compressed_ok = FALSE;
  1660.             }
  1661.         
  1662.         }
  1663.       else 
  1664.         {
  1665.           compressed = FALSE;
  1666.           /* copy name */
  1667.           strcpy(compress_name,fnamecopy);
  1668.          }
  1669.  
  1670.       if ((!compressed) || (compressed_ok))
  1671.         {
  1672.     /* now attempt to put it in the queue and go on as long as the queue is not too full
  1673.              if it is too full sleep and try again */
  1674.            queue_elements = 0;
  1675.            do
  1676.             {
  1677.              queue_elements = read_elements_in_queue();
  1678.              if (queue_elements >= 29)
  1679.                {
  1680.                 /* wait */
  1681.                 Sleep(500);
  1682.                 if (debug_child)
  1683.                   {
  1684.                    printf("Woke up from .5 second wait queue size was %d \n",queue_elements);
  1685.                    fflush(stdout);
  1686.                   }
  1687.                 }
  1688.               } while (queue_elements >= 29);
  1689.  
  1690.            /*      if we got here there is room in the queue to do it */
  1691.               strcpy(element.original_filename,savepath);
  1692.               strcpy(element.temp_filename,compress_name);
  1693.               element.size = size;
  1694.               element.attrs = dwAttrs;
  1695.               element.lowdate = wtime.dwLowDateTime;
  1696.               element.highdate = wtime.dwHighDateTime;
  1697.               element.compressed = compressed;
  1698.  
  1699.               if (debug_child)
  1700.                 {
  1701.                   printf("Filled in element with: \n");
  1702.                   printf("original name = %s \n",element.original_filename);
  1703.                   printf("temp name = %s \n",element.temp_filename);
  1704.                   printf("size = %d attrs = %d lowdate = %d highdate = %d \n",
  1705.                       element.size,element.attrs,element.lowdate,element.highdate);
  1706.                   fflush(stdout);
  1707.                  }
  1708.                 push_element(element);
  1709.          
  1710.          } /* compressed ok or not compressed */
  1711.          } /* path ok */
  1712.       } /* opened ok */
  1713.    }
  1714.  
  1715.  /* --------------------------------------------------------------------------------------*/
  1716.  
  1717.  void backup_index_file(filename,size,attributes)
  1718.     char filename[];
  1719.     DWORD size;
  1720.  
  1721.     {
  1722.       char lbuffer[bsize1];
  1723.       HANDLE hFile;
  1724.       LPTSTR ppszFilePart;    /* address of filename in path    */
  1725.       DWORD rvalue;
  1726.       int start_block = current_tape_block_number;
  1727.       int ldwBytesRead = 0;
  1728.  
  1729.       
  1730.      hFile = open_file_for_read(filename,TRUE);
  1731.      
  1732.   /* now since file opened ok write out first buffer with file name and
  1733.                size */
  1734.      if (hFile == NULL) /* skip it since it couldn't be opened */
  1735.        {
  1736.          ++filesskipped;
  1737.          printf("Warning skipping file %s which could not be opened. \n",filename);
  1738.          fflush(stdout);
  1739.        }
  1740.  
  1741.      else
  1742.  
  1743.       {
  1744.  
  1745.     if (debug)
  1746.       {
  1747.         printf("TapeIO:--> Backing up %s size is %ld \n",filename,size);
  1748.         fflush(stdout);
  1749.       }         
  1750.        /* write full path to file */
  1751.        /* but erase first 3 chars ie i:\ so that restore is not drive specific */
  1752.  
  1753.     rvalue = GetFullPathName((LPCSTR)filename,buffersize,(LPTSTR)lbuffer,&ppszFilePart);
  1754.     if (rvalue == 0)
  1755.        {
  1756.          CloseHandle(hFile);
  1757.          report_error(" Path + file name longer than max buffer size (512)\n",rvalue,severe);
  1758.        }
  1759.     
  1760.     lbuffer[0] = ' ';
  1761.        lbuffer[1] = ' ';
  1762.     lbuffer[2] = ' ';
  1763.       
  1764.     if (debug)
  1765.       {
  1766.         printf("TapeIO:--> Backing up %s size is %ld \n",lbuffer,size);
  1767.         fflush(stdout);
  1768.       }         
  1769.     
  1770.      
  1771.     sprintf(lbuffer + rvalue," %d %d %d %d",size,0, 
  1772.                0,0);
  1773.   
  1774.        write_tape_block(lbuffer);
  1775.        
  1776.     if (debug)
  1777.       {
  1778.         printf("wrote block for file header %2048s \n",lbuffer);
  1779.         fflush(stdout);
  1780.       }
  1781.  
  1782.     do {
  1783.           dwBytesRead = read_file_block(hFile,lbuffer);
  1784.           if (dwBytesRead > 0)
  1785.             {  
  1786.               if (debug)
  1787.                 {
  1788.                   printf("TapeIO:-->Attempting to write the buff to tape\n");
  1789.                   fflush(stdout);
  1790.                  }
  1791.                        
  1792.               write_tape_block(lbuffer);
  1793.                     
  1794.              } /* bytes > 0 */
  1795.   
  1796.         } while (dwBytesRead == buffersize);
  1797.       /* close the file handle */
  1798.       CloseHandle(hFile);
  1799.           
  1800.       ++filesuncompressed;
  1801.       total_backup_size = total_backup_size + size;
  1802.       total_original_size = total_original_size + size;
  1803.       } /* skip file */
  1804.     }
  1805.  /* --------------------------------------------------------------------------------------*/
  1806.  
  1807.  void mt_backup_files()
  1808.  
  1809.        /* modify routine to simply read queue element and backup the file if not index file
  1810.         and compression on */
  1811.  
  1812.     {
  1813.  
  1814.       char lbuffer[bsize1];
  1815.       HANDLE hFile, hMapHandle;
  1816.       unsigned int compress_size = 0;
  1817.       int elements_in_queue;
  1818.       READ_QUEUE_TYPE element;
  1819.       FILETIME wtime;
  1820.       unsigned short dostime;
  1821.       unsigned short dosdate;
  1822.       char file_date[9];
  1823.       int start_block = current_tape_block_number;
  1824.       BOOLEAN mapok = FALSE;
  1825.       LPVOID memory_address = NULL;
  1826.       DWORD fsize;
  1827.       int compress_size_to_write = 0;
  1828.       BOOLEAN skipping_file = FALSE;
  1829.       BOOLEAN old_method_ok = FALSE;
  1830.       BOOLEAN unmap_ok = FALSE;
  1831.  
  1832.       /* lgk add case to handle uncompressed file below threshold and to turn off file mapping */
  1833.  
  1834.  elements_in_queue = 0;
  1835.  do  /* loop until we are signaled that we are done and there are no more elements to be processed */
  1836.  
  1837.    {
  1838.     /* get element from queue if it is waiting if not sleep for two seconds and try again */
  1839.     
  1840.      do /* loop while there are no elements to process and we are not done */
  1841.        {
  1842.           elements_in_queue = read_elements_in_queue();
  1843.  
  1844.           if ((elements_in_queue == 0) && (!processed_all_files))
  1845.             Sleep(500);
  1846.        } while ((elements_in_queue == 0) && (!processed_all_files));
  1847.  
  1848.     /* now that we have an item read it */
  1849.     /* need to read it again here because between the time elements was 0 and the end of
  1850.        the while loop processed_all_files is getting set to true and the loop is exiting
  1851.        without realizing about the last few files in the queue */
  1852.  
  1853.     elements_in_queue = read_elements_in_queue();
  1854.     if (elements_in_queue > 0)
  1855.       {
  1856.            element = pop_element();
  1857.         /* now process_it */
  1858.            compress_size = 0;
  1859.         start_block = current_tape_block_number;
  1860.  
  1861.     if (debug)
  1862.       {
  1863.         printf("TapeIO:--> Backing up %s aka %s size is %ld \n",
  1864.              element.original_filename,element.temp_filename,element.size);
  1865.         fflush(stdout);
  1866.       }         
  1867.  
  1868.         skipping_file = FALSE;
  1869.         old_method_ok = FALSE;
  1870.         mapok = FALSE;
  1871.         memory_address = NULL;
  1872.  
  1873.            hFile = open_file_for_read(element.temp_filename,TRUE);
  1874.         if (hFile == NULL) /* skip it since it couldn't be opened */
  1875.           {
  1876.            ++filesskipped;
  1877.            printf("Warning skipping file %s since temp file/tempfile %s could not be opened. \n",
  1878.            element.original_filename,element.temp_filename);
  1879.            fflush(stdout);
  1880.            skipping_file = TRUE;
  1881.            mapok = FALSE;
  1882.           }
  1883.        else    /* skipping */
  1884.         {
  1885.          sprintf(lbuffer,"%350s %d %d %d %d",element.original_filename,element.size,element.attrs, 
  1886.                element.lowdate,element.highdate);
  1887.          write_tape_block(lbuffer);
  1888.          if (debug)
  1889.            {
  1890.              printf("wrote block for file header %2048s \n",lbuffer);
  1891.              fflush(stdout);
  1892.            }
  1893.     
  1894.     /* only use file mapping if on */
  1895.  
  1896.     if (file_mapping)
  1897.       {
  1898.        mapok = TRUE;   
  1899.       /* lgk new code here to speed things up by reading the entire file into a memory
  1900.         buffer and then writting to tape if this fails default to the old method */
  1901.             
  1902.       /* get the file size */
  1903.       fsize = GetFileSize(hFile,NULL);
  1904.       if (fsize == 0xFFFFFFFF)
  1905.         { 
  1906.           if (debug)
  1907.             {
  1908.               printf("Getfile size for %s failed \n",element.temp_filename);
  1909.               fflush(stdout);
  1910.               CloseHandle(hFile);
  1911.               mapok = FALSE;
  1912.               }
  1913.          }
  1914.        else
  1915.         {
  1916.           hMapHandle = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,"compress_map");
  1917.           if (hMapHandle == NULL)
  1918.             {
  1919.               if (debug)
  1920.                 { 
  1921.                   printf("Map file did not open correctly rvalue = %d \n",GetLastError());
  1922.                   fflush(stdout);
  1923.                   CloseHandle(hFile);
  1924.                   mapok = FALSE;
  1925.                 }
  1926.             }
  1927.            else
  1928.             {
  1929.               /* now map the handle into memory */
  1930.               memory_address = MapViewOfFile(hMapHandle,FILE_MAP_READ,0,0,0);
  1931.               if (memory_address == NULL)
  1932.                 { 
  1933.                  printf("Map file view did not open correctly rvalue = %d \n",GetLastError());
  1934.                  fflush(stdout);
  1935.                  CloseHandle(hFile);
  1936.                  CloseHandle(hMapHandle);
  1937.                  mapok = FALSE;
  1938.                 }
  1939.               else
  1940.                {
  1941.                 /* ok now process the memory in blocks that the tape drive can handle */
  1942.                 compress_size = 0;
  1943.                 mapok = TRUE;
  1944.  
  1945.                 do 
  1946.                   {
  1947.                     write_tape_block((char *)((DWORD)(memory_address) + compress_size));
  1948.                    compress_size = compress_size + buffersize;
  1949.                   } while (compress_size < fsize);
  1950.                 /* ok reset compress_size which got too big */
  1951.                 compress_size = fsize;
  1952.  
  1953.                } /* ok address */
  1954.              } /* ok handle */
  1955.             } /* ok size */
  1956.  
  1957.    /* clean up if worked ok otherwise try other method */
  1958.    if (mapok)
  1959.      {
  1960.       if (debug)
  1961.         {
  1962.           printf("file map method worked \n");
  1963.           fflush(stdout);
  1964.         }
  1965.         unmap_ok = TRUE;
  1966.         unmap_ok = UnmapViewOfFile(memory_address);
  1967.         if (!unmap_ok)
  1968.          {
  1969.           printf("Warning unmapping of file view failed error code = %d \n",GetLastError());
  1970.           fflush(stdout);
  1971.          }
  1972.         /* now close the handles */
  1973.         CloseHandle(hMapHandle);
  1974.         CloseHandle(hFile);
  1975.       } /* mapped ok */
  1976.  
  1977.       } /* end file mapping on */
  1978.  
  1979.       else /* either it failed or don't want file mapping */
  1980.       {
  1981.  
  1982.  
  1983.     do {
  1984.           dwBytesRead = read_file_block(hFile,lbuffer);
  1985.           if (dwBytesRead > 0)
  1986.             {  
  1987.               if (debug)
  1988.                 {
  1989.                   printf("TapeIO:-->Attempting to write the buff to tape\n");
  1990.                   fflush(stdout);
  1991.                  }
  1992.                        
  1993.               write_tape_block(lbuffer);
  1994.               compress_size = compress_size + dwBytesRead;
  1995.                     
  1996.              } /* bytes > 0 */
  1997.   
  1998.         } while (dwBytesRead == buffersize);
  1999.  
  2000.       /* close the file handle */
  2001.       CloseHandle(hFile);
  2002.       old_method_ok = TRUE;
  2003.     }  /* end of old method */
  2004.     
  2005.     if (old_method_ok || mapok)
  2006.       {
  2007.             /* now handle the index entry */
  2008.  
  2009.             wtime.dwLowDateTime = element.lowdate;
  2010.             wtime.dwHighDateTime = element.highdate;
  2011.  
  2012.             /* need to convert to file date for the index entry */
  2013.           
  2014.           if (element.compressed)
  2015.              {
  2016.                compress_size_to_write = compress_size;
  2017.                total_backup_size = total_backup_size + compress_size;
  2018.              }
  2019.           else 
  2020.              {
  2021.                compress_size_to_write = 0;
  2022.                total_backup_size = total_backup_size + element.size;
  2023.              }
  2024.  
  2025.           if (!FileTimeToDosDateTime(&wtime,&dosdate,&dostime))
  2026.             {
  2027.              
  2028.              printf("Warning couldn't convert file date to dos date using todays date \n");
  2029.              fflush(stdout);
  2030.              write_index_entry(element.original_filename,element.size,compress_size_to_write,
  2031.                          todays_date,start_block);
  2032.             }
  2033.            /* ok we got the date no set it into varibles and convert to string */
  2034.            else
  2035.            { 
  2036.             int nDay = dosdate & 0x1f;
  2037.             int nMonth = (dosdate >> 5) & 0x0f;
  2038.             int nYear = (dosdate >> 9) + 80;
  2039.  
  2040.             /* now convert to string */
  2041.             sprintf(file_date,"%02d-%02d-%02d",nMonth,nDay,nYear);
  2042.             write_index_entry(element.original_filename,element.size,compress_size_to_write,
  2043.                         file_date,start_block);
  2044.            }
  2045.       
  2046.       /* only delete file if actually was temp file don't do it for uncompressed files */
  2047.       if (element.compressed)
  2048.         {
  2049.          ++filescompressed;
  2050.          DeleteFile(element.temp_filename);
  2051.         }
  2052.       else ++filesuncompressed;
  2053.  
  2054.       total_original_size = total_original_size + element.size;
  2055.      } /* mpa ok or old meethod ok */
  2056.     } /* not skipping file */
  2057.    } /* we have an element */
  2058.   
  2059.   } while ((elements_in_queue != 0) || (!processed_all_files));
  2060.  } 
  2061.  
  2062. /* ------------------------------------------------------------------------------------- */
  2063.  void set_file_info(filename,lowtime,hightime,lattrs)
  2064.     
  2065.     char *filename;
  2066.     DWORD lowtime;
  2067.     DWORD hightime;
  2068.     DWORD lattrs;
  2069.  
  2070.    {
  2071.  
  2072.        FILETIME local_file_time;
  2073.       HANDLE writeHandle;
  2074.  
  2075.          /* attempt to set date and file attributes */
  2076.                if (lattrs != 0)
  2077.                  {
  2078.                   if (debug)
  2079.                     {
  2080.                      printf("Attempting to set file attributes to %d \n",lattrs);
  2081.                      fflush(stdout);
  2082.                     }
  2083.  
  2084.                if (!SetFileAttributes(filename,lattrs))
  2085.                   {
  2086.                    printf("Warning couldn't set file %s attributes to %s during restore \n",filename,lattrs);
  2087.                    fflush(stdout);
  2088.                   }
  2089.                  }
  2090.                 
  2091.                /* now fill in a wtime struct and attempt to reset the time */
  2092.                 local_file_time.dwLowDateTime = lowtime;
  2093.                 local_file_time.dwHighDateTime = hightime;
  2094.  
  2095.                 writeHandle = open_file_for_set_time(filename);
  2096.  
  2097.                 if (!SetFileTime(writeHandle,NULL,NULL,&local_file_time))
  2098.                   {
  2099.                    printf("Warning couldn't set file last write time for %s error = %d \n",
  2100.                            filename,GetLastError());
  2101.                    fflush(stdout);
  2102.                   }
  2103.                 CloseHandle(writeHandle);
  2104.       }
  2105.  
  2106.   /* --------------------------------------------------------------------------------------*/
  2107.  
  2108.  void restore_file(filename,size,csize,isindexfile)
  2109.     char *filename;
  2110.     int size;
  2111.     int csize;
  2112.     BOOLEAN isindexfile;
  2113.  
  2114.           /* return the restored file name */
  2115.           /* if it is the index file create it as orinally but append the temp drive to it */
  2116.  
  2117.     {
  2118.       char temppath[400];
  2119.       BOOLEAN compressed = FALSE;
  2120.       char lbuffer[bsize1];
  2121.       HANDLE hFile;
  2122.       int restore_size;
  2123.       DWORD lcopied = 0;
  2124.       unsigned int rvalue2;
  2125.       char TempFileName[400];
  2126.       char *nameloc;
  2127.       BOOLEAN done;
  2128.       int size_restored_so_far = 0;
  2129.       char lname[400];
  2130.       DWORD lowtime;
  2131.       DWORD hightime;
  2132.       DWORD lattrs;
  2133.       int lsize;
  2134.       
  2135.           
  2136.       if (csize > 0)
  2137.        {
  2138.         compressed = TRUE;
  2139.         restore_size = csize;
  2140.               /* create a temp file name/path to restore the file to */
  2141.      
  2142.        }  /* compress */
  2143.      else
  2144.         {
  2145.          compressed = FALSE;
  2146.          restore_size = size;
  2147.         }
  2148.  
  2149.     
  2150.       /* get the temp path for a compress restore or restore of the index file */
  2151.      
  2152.      if (compressed || isindexfile)
  2153.        {
  2154.        lcopied = GetTempPath(100,temppath);
  2155.        if (lcopied <= 0)
  2156.           {
  2157.            report_error(" Cannot retrieve temporary directory path \n",0,severe);
  2158.           }
  2159.        else
  2160.          {
  2161.            /* now create a temp name and concat path to name */
  2162.              rvalue2 = GetTempFileName(temppath, /* dir. for temp. files            */
  2163.                "NEW",                /* temp. filename prefix           */
  2164.                  0,                    /* create unique name w/ sys. time */
  2165.              (LPTSTR) TempFileName); /* buffer for name                 */
  2166.  
  2167.            if (rvalue2 == 0)
  2168.              {
  2169.                report_error(" Getting temp file name for decompression \n",rvalue2,severe);
  2170.              }
  2171.            else 
  2172.                {
  2173.                 /* concat path to name */
  2174.                 /* we only need to name form the temp file as it appends \temp\ to it
  2175.                    and we already have the temppath */
  2176.                   nameloc = strrchr(TempFileName,'\\');
  2177.                   /* skip over slash */
  2178.                   ++nameloc;
  2179.  
  2180.                   strcat(temppath,nameloc);
  2181.                 
  2182.                 if (debug)
  2183.                   {
  2184.                     printf("temp file for decompress = %s \n",temppath);
  2185.                     fflush(stdout);
  2186.                   }
  2187.    
  2188.                    } /* name ok */
  2189.              } /* path ok */ 
  2190.           } /* for index or compressed file */
  2191.       else
  2192.         {
  2193.           /* not compressed or index means regular file uncompressed to copy file name to temppath */
  2194.           strcpy(temppath,filename);
  2195.         }
  2196.  
  2197.      if (debug)
  2198.        {
  2199.         printf("TapeIO:--> Restoring file about to read name block \n");
  2200.         fflush(stdout);
  2201.        }         
  2202.       read_tape_block(lbuffer);
  2203.       if (debug)
  2204.          {
  2205.           printf("In restore file got name block number %s\n",lbuffer);
  2206.           fflush(stdout);
  2207.          }
  2208.  
  2209.     
  2210.     if (isindexfile)
  2211.       {
  2212.        /* get the size out of the buffer */
  2213.         sscanf(lbuffer,"%350s %10d",filename,&size);
  2214.         restore_size = size; /* index file is not compressed */
  2215.         if (debug)
  2216.           {
  2217.             printf("got name/size for index file name = %s size = %d \n",filename,size);
  2218.             fflush(stdout);
  2219.           }
  2220.       }
  2221.  
  2222.    /* check to make sure name in file matches restore name ignore check for index file */
  2223.    else
  2224.       {     /* must skip over first 3 characters in buffer that had e:\ etc. in it */
  2225.        
  2226.          /* get times and attributes */
  2227.         lsize = 0;
  2228.         lattrs = 0;
  2229.         lowtime = 0;
  2230.         hightime = 0;
  2231.         sscanf(lbuffer + 3,"%s %d %d %d %d",lname,&lsize,&lattrs,&lowtime,&hightime);
  2232.  
  2233.        if (strncmp(filename,lname,strlen(filename)) != 0)
  2234.          {
  2235.           printf("Tape IO Error Name in buffer %350s does not match restore file name %s \n",
  2236.                      lbuffer,filename);
  2237.           fflush(stdout);
  2238.           report_error(" ",0,severe);
  2239.          }
  2240.       }
  2241.   /* now restore the file wherever (to temppath)  */
  2242.      
  2243.       if (debug)
  2244.         {
  2245.           printf("attempting to open for write/restore: %s \n",temppath);
  2246.           fflush(stdout);
  2247.         }
  2248.  
  2249.       hFile = open_file_for_write(temppath);
  2250.       done = FALSE;
  2251.       size_restored_so_far = 0;
  2252.  
  2253.       /* problem here for file of 0 length we don't want to read the block or we are off when
  2254.          it comes to the next file since a block was not written out */
  2255.  
  2256.      /* restore the file pointed to by hfile */
  2257.    if (restore_size > 0)
  2258.      {
  2259.     do {
  2260.           read_tape_block(lbuffer);
  2261.               
  2262.               if (debug)
  2263.                 {
  2264.                   printf("TapeIO:-->Attempting to write the buff to file\n");
  2265.                   fflush(stdout);
  2266.                  }
  2267.                        
  2268.               if ((size_restored_so_far + blocksize) <= restore_size)
  2269.                 {
  2270.                   write_file_block(hFile,lbuffer,blocksize);
  2271.                   if ((size_restored_so_far + blocksize) == restore_size)
  2272.                     done = TRUE;
  2273.  
  2274.                   size_restored_so_far = size_restored_so_far + blocksize;
  2275.                  }
  2276.  
  2277.                else /* write last partial block */
  2278.                  {
  2279.                    write_file_block(hFile,lbuffer,restore_size - size_restored_so_far);
  2280.                    if (debug)
  2281.                      {
  2282.                        printf("Writing out last partial block of %d characters \n",
  2283.                                restore_size - size_restored_so_far);
  2284.                        fflush(stdout);
  2285.                       }
  2286.                      done = TRUE;
  2287.                      size_restored_so_far = size_restored_so_far + (restore_size - size_restored_so_far);
  2288.                      
  2289.                  } /* bytes > 0 */
  2290.  
  2291.         } while (!done);
  2292.       } /* end of size > 0 */
  2293.  
  2294.       /* close the file handle */
  2295.       CloseHandle(hFile);
  2296.     
  2297.     /* now if the file was uncompressed or the index file 
  2298.         we are done otherwise if it was compressed we need to decompress it to the
  2299.         original file */
  2300.  
  2301.        if (!compressed)
  2302.          {
  2303.               if (!isindexfile)
  2304.                  set_file_info(filename,lowtime,hightime,lattrs);
  2305.                    
  2306.               if ((!quiet_mode) && (!isindexfile))
  2307.                 {
  2308.                   printf("Restored Uncompressed file %s \n",filename);
  2309.                   fflush(stdout);
  2310.                 }
  2311.  
  2312.  
  2313.               ++filesuncompressed;
  2314.                 total_bytes_read = total_bytes_read + size;
  2315.               /* if index file copy name to ifle name */
  2316.               if (isindexfile)
  2317.                 strcpy(filename,temppath);
  2318.          }
  2319.  
  2320.         else /* compressed */
  2321.           {
  2322.                /* now decompress it */
  2323.                /* when decompressing the name somehow gets changes to / probably in the mkdir
  2324.                   routine can't find it so copy it, and copy back after decompress */
  2325.             strcpy(lname,filename);
  2326.  
  2327.             if (decompress_file(filename,temppath) == -1)
  2328.               {
  2329.                 printf("Warning couldn't decompress file %s \n",lname);
  2330.                 printf("File NOT RESTORED \n");
  2331.                 printf("Leaving temp file %s for an attempt at manual decompression. \n",temppath);
  2332.                 fflush(stdout);
  2333.                }
  2334.              else
  2335.                {
  2336.                  /* copy back */
  2337.                  strcpy(filename,lname);
  2338.  
  2339.                  set_file_info(filename,lowtime,hightime,lattrs);
  2340.                  if (!quiet_mode)
  2341.                    {
  2342.                      printf("Restored Compressed file %s\n",filename);
  2343.                      fflush(stdout);
  2344.                    } 
  2345.                  ++filescompressed;
  2346.                  total_bytes_read = total_bytes_read + csize;
  2347.                  DeleteFile(temppath);
  2348.                 }
  2349.                 
  2350.           }
  2351.  
  2352.     }
  2353.  
  2354.    /* -------------------------------------------------------------------------------------- */
  2355.    void print_backup_stats()
  2356.      {
  2357.        DWORD total_time;
  2358.        unsigned long int minutes;
  2359.        unsigned long int backuprate;
  2360.  
  2361.        total_time = GetTickCount() - start_time;
  2362.  
  2363.         if (debug)
  2364.           printf("total time = %d \n",total_time);
  2365.  
  2366.        minutes = (int)(((float)total_time) / ((float)60000.0000));
  2367.                                           /* 60 * 1000 which equal the number 
  2368.                                             of milliseconds in a minute */
  2369.  
  2370.        backuprate = (int)(((float)total_original_size / (float)minutes) / (float)1024.000);
  2371.        if (!quiet_mode)
  2372.          {
  2373.        printf("\n----------------------------------------------------------------\n");
  2374.        printf("Files Backed Up          --> %d \n",filescompressed+filesuncompressed);
  2375.        printf("  No Compressed          --> %d \n",filescompressed);
  2376.        printf("  No UnCompressed        --> %d \n",filesuncompressed);
  2377.        printf("Files Skipped            --> %d \n\n",filesskipped);
  2378.        printf("Original Size            --> %d \n",total_original_size);
  2379.        printf("Size on Tape             --> %d \n",total_backup_size); 
  2380.        printf("Compression Ratio        --> (%2d%%)\n\n",
  2381.           (int)(100.00 * (1.000 - (float)((float)total_backup_size/(float)total_original_size))));
  2382.        printf("Backup Time (minutes)    --> %d \n",minutes);
  2383.        printf("Backup Rate K/minute     -->    %d \n",backuprate);
  2384.        printf("\n----------------------------------------------------------------\n");
  2385.        fflush(stdout);
  2386.        }
  2387.      }
  2388.  
  2389.   /* --------------------------------------------------------------------------------------- */
  2390.    void print_restore_stats()
  2391.      {
  2392.        DWORD total_time;
  2393.        unsigned long int minutes;
  2394.        unsigned long int restoreuprate;
  2395.  
  2396.        total_time = GetTickCount() - start_time;
  2397.  
  2398.         if (debug)
  2399.           printf("total time = %d \n",total_time);
  2400.  
  2401.        minutes = (int)(((float)total_time) / ((float)60000.0000));
  2402.                                           /* 60 * 1000 which equal the number 
  2403.                                             of milliseconds in a minute */
  2404.  
  2405.        restoreuprate = (int)(((float)total_bytes_read / (float)minutes) / (float)1024.000);
  2406.        if (!quiet_mode)
  2407.          {
  2408.        printf("\n----------------------------------------------------------------\n");
  2409.        printf("Files Restored           --> %d \n",filescompressed+filesuncompressed);
  2410.        printf("  No Compressed          --> %d \n",filescompressed);
  2411.        printf("  No UnCompressed        --> %d \n\n",filesuncompressed);
  2412.        printf("Total Bytes Restored     --> %d \n",total_bytes_read); 
  2413.        printf("Restore Time (minutes)   --> %d \n",minutes);
  2414.        printf("Restore Rate K/minute    -->    %d \n",restoreuprate);
  2415.        printf("\n----------------------------------------------------------------\n");
  2416.        fflush(stdout);
  2417.        }
  2418.      }
  2419.   /* --------------------------------------------------------------------------------------- */
  2420.    void write_directory_file()
  2421.   {
  2422.    int fsize;
  2423.  
  2424.    fsize = ftell(TempIndexFile);
  2425.    close_index_file();
  2426.    /* size is not important for this file */
  2427.    /*ignore drive letter on file */
  2428.    /* we need the file size here otherwise it will not know how much to restore */
  2429.  
  2430.    backup_index_file(TempIndexFileName,fsize);
  2431.    /* now delete the file */
  2432.    DeleteFile(TempIndexFileName);
  2433.   
  2434.   }
  2435.  
  2436. /* ----------------------------------------------------------------------------------- */
  2437.                         
  2438. void process_write_directory(SearchString,process_subdirs)
  2439.   char *SearchString;
  2440.   BOOLEAN process_subdirs;
  2441.  
  2442. /* if process subdirs set first go through entire directory then do it again and process subdirs */
  2443.  
  2444.  {
  2445.      WIN32_FIND_DATA FileData;
  2446.      HANDLE hSearch;
  2447.      BOOLEAN done = FALSE;
  2448.      BOOLEAN rvalue;
  2449.      BOOLEAN onefound = FALSE;
  2450.  
  2451. /* Start searching for  files in the current directory. */
  2452.  
  2453.    hSearch = FindFirstFile(SearchString, &FileData);
  2454.    if (hSearch == INVALID_HANDLE_VALUE)
  2455.      {
  2456.        /* no files in search parameters */
  2457.        if ((debug) && (!process_subdirs))
  2458.          {
  2459.            printf("TapeIO:--> Warning no files found in search parameter %s \n",SearchString);   
  2460.            fflush(stdout);
  2461.          }
  2462.         if (!process_subdirs)
  2463.           {
  2464.             FindClose(hSearch);
  2465.               return; /* cannot do this directory */
  2466.           }
  2467.      }
  2468.     else onefound = TRUE;
  2469.     
  2470.     if (onefound) 
  2471.       {  
  2472.    /* get size and process file only gets here if handle opened ok */
  2473.    /* skip directories */
  2474.      if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
  2475.       mt_compress_file(FileData.cFileName,FileData.nFileSizeLow);
  2476.   
  2477.      /* loop through remainder of files */
  2478.  
  2479.     do {
  2480.        rvalue = FindNextFile(hSearch,&FileData);
  2481.        if ((rvalue == FALSE) && (GetLastError() == ERROR_NO_MORE_FILES))
  2482.          {
  2483.             done = TRUE;
  2484.             FindClose(hSearch);
  2485.          }  
  2486.  
  2487.        else
  2488.           {
  2489.           if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
  2490.            mt_compress_file(FileData.cFileName,FileData.nFileSizeLow);
  2491.             }
  2492.         } while (!done);
  2493.  
  2494.      } /* onefound */
  2495.  
  2496.  /* now if process subdirs set go through and stop at all subdirs and recurse */
  2497.   if (process_subdirs)
  2498.     {
  2499.       done = FALSE;
  2500.  
  2501.       /* Start searching for all subdirectories to recurse on */
  2502.       hSearch = FindFirstFile("*", &FileData);
  2503.       if (hSearch == INVALID_HANDLE_VALUE)
  2504.         {
  2505.            
  2506.         FindClose(hSearch);
  2507.           return; /* cannot do this directory */
  2508.  
  2509.         } /* no files */
  2510.  
  2511.    /* now check if file is subdir if so process if it is not "." or ".." */
  2512.       if ((strncmp(FileData.cFileName,".",1) != 0) &&
  2513.          (strncmp(FileData.cFileName,"..",2) != 0))
  2514.           {
  2515.             /* ok is not bs names */
  2516.              
  2517.              if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
  2518.                 {
  2519.               
  2520.                    if (SetCurrentDirectory(FileData.cFileName) == FALSE)
  2521.                       {
  2522.                        printf("TapeIO:--> Warning Couldn't change directory to %s \n",FileData.cFileName);
  2523.                       fflush(stdout);
  2524.                     }
  2525.                    else {
  2526.                           process_write_directory(SearchString,process_subdirs);
  2527.                           /* set current directory back */
  2528.                           SetCurrentDirectory("..");  
  2529.                          }
  2530.                  } /* is directory */
  2531.             } /* is not . or .. */
  2532.  
  2533.     /* when it returns recurse through remainder of subdirs */
  2534.     do
  2535.      {
  2536.        rvalue = FindNextFile(hSearch,&FileData);
  2537.        if ((rvalue == FALSE) && (GetLastError() == ERROR_NO_MORE_FILES))
  2538.          {
  2539.             done = TRUE;
  2540.             FindClose(hSearch);
  2541.          }  
  2542.  
  2543.        else
  2544.           {
  2545.           /* now check if file is subdir if so process if it is not "." or ".." */
  2546.             if ((strncmp(FileData.cFileName,".",1) != 0) &&
  2547.                 (strncmp(FileData.cFileName,"..",2) != 0))
  2548.               {
  2549.                 /* ok is not bs names */
  2550.                   /* instead of using getfileattrs dwFileAttributes */
  2551.  
  2552.                  if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
  2553.                      {
  2554.                         
  2555.                    /* is a directory so set directory and recurse */
  2556.                    if (SetCurrentDirectory(FileData.cFileName) == FALSE)
  2557.                      {
  2558.                       printf("TapeIO:--> Warning Couldn't change directory to %s \n",FileData.cFileName);
  2559.                       fflush(stdout);
  2560.                      }
  2561.                    else {
  2562.                           process_write_directory(SearchString,process_subdirs);
  2563.                            SetCurrentDirectory("..");
  2564.                          }
  2565.                   } /* is directory */
  2566.               } /* is not . or .. */
  2567.  
  2568.             } /* else not last file */
  2569.        } while (!done);
  2570.  
  2571.     } /* process subdirs */
  2572.   }
  2573.  
  2574.   /* ------------------------------------------------------------------------------------------ */
  2575.  void mt_process_write_directory(LPVOID dummy)
  2576.    {  
  2577.      /* call read process write directory */
  2578.      /* get the global values */
  2579.  
  2580.      if (debug_child)
  2581.         {
  2582.           printf("in top level mt process write directory search string = %s subdirs = %d \n",
  2583.                    Global_SearchString,global_process_subdirs);
  2584.           fflush(stdout);
  2585.          }
  2586.        process_write_directory(Global_SearchString,global_process_subdirs);
  2587.            if (debug_child)
  2588.          {
  2589.            printf("in thread done processing files \n");
  2590.            fflush(stdout);
  2591.          }
  2592.         processed_all_files = TRUE;
  2593.         thread_active = FALSE;
  2594.  
  2595.    }
  2596.  
  2597. /* ------------------------------------------------------------------------------------ */
  2598.   void space_sequential_filemarks(no_marks)
  2599.        DWORD no_marks;
  2600.    {
  2601.      DWORD rvalue;
  2602.      
  2603.      if (debug)
  2604.         {
  2605.          printf("Attempting to Space %d Seqential file marks\n",no_marks);
  2606.          fflush(stdout);
  2607.         }
  2608.       
  2609.           rvalue = SetTapePosition(hTape,TAPE_SPACE_SEQUENTIAL_FMKS,0,no_marks,0,FALSE); 
  2610.           if (rvalue != NO_ERROR)
  2611.             report_error(" Tape positioning by sequential filemarks error ",rvalue,severe);
  2612.         
  2613.     }
  2614. /* ------------------------------------------------------------------------------------ */
  2615.     void space_scsi_blocks(no_blocks)
  2616.      DWORD no_blocks;
  2617.    {
  2618.      DWORD rvalue;
  2619.         
  2620.         if (debug)
  2621.           {
  2622.             printf("Attempting to Space %d Scsi data blocks \n",no_blocks);
  2623.             fflush(stdout);
  2624.           }
  2625.        
  2626.          rvalue = SetTapePosition(hTape,TAPE_SPACE_RELATIVE_BLOCKS,0,no_blocks,0,FALSE); 
  2627.           if (rvalue != NO_ERROR)
  2628.             report_error(" Tape positioning by scsi (relative) block error ",rvalue,severe);
  2629.         
  2630.     } 
  2631.   /* ---------------------------------------------------------------------------------- */
  2632.  
  2633.    void eject_tape()
  2634.    {
  2635.       DWORD rvalue;
  2636.  
  2637.        rvalue = PrepareTape(hTape,TAPE_UNLOAD,FALSE);
  2638.     
  2639.      if (rvalue != NO_ERROR)
  2640.         {
  2641.            report_error("Ejecting tape ",rvalue,severe);
  2642.         }
  2643.     else
  2644.         {
  2645.           if (debug)
  2646.             {
  2647.               printf("TapeIO:-->Unloaded/Ejected Tape \n");
  2648.               fflush(stdout);
  2649.              }
  2650.           }
  2651.   }
  2652.  
  2653. /*   ---------------------------------------------------------------------------------- */
  2654.  void list_tape()
  2655.    
  2656.    {
  2657.     
  2658.      int element_number = 0;
  2659.      
  2660.       read_tape_index();
  2661.          printf("Number      Saveset Name   Original Size   Compressed Size   Date \n");
  2662.       printf("__________________________________________________________________\n");
  2663.       for (element_number = 0; element_number < max_save_sets; element_number++)
  2664.           dump_header_element(element_number);
  2665.       printf("\nListing Complete\n\n");
  2666.       fflush(stdout);
  2667.  
  2668.     
  2669.    }
  2670.  
  2671. /* ------------------------------------------------------------------------------------ */
  2672.  int find_free_saveset_element()
  2673.  
  2674.   {
  2675.     BOOLEAN found = FALSE;
  2676.     int number = 0;
  2677.     int element_number = 0;
  2678.  
  2679.     for (element_number = 0; element_number < max_save_sets; element_number++)
  2680.        {
  2681.         if (strncmp(raw_tape_header.header[element_number].saveset_name,"EMPTY001_____",13) == 0)
  2682.           {
  2683.             number = element_number;
  2684.             found = TRUE;
  2685.             break;
  2686.           }
  2687.         }
  2688.        if (found)
  2689.          return(number);
  2690.        else return(-1); 
  2691.  
  2692.     }
  2693.  
  2694.  /* ------------------------------------------------------------------------------------- */
  2695.  BOOLEAN get_index_file_entry(indexrec)
  2696.    INDEX_REC_TYPE *indexrec;
  2697.    {
  2698.   
  2699.      int lsize;
  2700.      int csize;
  2701.      int sblock;
  2702.      char ldate[9];
  2703.      char fname[351];
  2704.      int rvalue;
  2705.  
  2706.      rvalue = fscanf(TempIndexFile,"%350s %10d %10d %8s %10d \n",fname,&lsize,&csize,ldate,&sblock);
  2707.       if (rvalue == 0)
  2708.          report_error("Reading index file entry \n",0,severe);
  2709.  
  2710.       if (rvalue == EOF)
  2711.         {
  2712.          if (debug)
  2713.            {
  2714.              printf("EOF of index file found \n");
  2715.              fflush(stdout);
  2716.             }
  2717.           fclose(TempIndexFile);
  2718.           return(FALSE);
  2719.          }
  2720.  
  2721.       if (debug)
  2722.         {
  2723.           printf("Successfully retrieved index entry %s %d %d %8s %d\n",fname,lsize,csize,ldate,sblock);
  2724.           fflush(stdout);
  2725.         }
  2726.  
  2727.      /* fill in fields */
  2728.      indexrec->original_size = lsize;
  2729.      indexrec->compressed_size = csize;
  2730.      strcpy(indexrec->fname,fname);
  2731.      strcpy(indexrec->date,ldate);
  2732.      indexrec->start_block = sblock;
  2733.  
  2734.        if (debug)
  2735.         {
  2736.           printf("Successfully filled in index entry %s %d %d %8s %d\n",
  2737.           indexrec->fname,
  2738.           indexrec->original_size,
  2739.           indexrec->compressed_size,
  2740.           indexrec->date,
  2741.           indexrec->start_block);
  2742.           fflush(stdout);
  2743.         }
  2744.        return(TRUE);
  2745.      
  2746.      }
  2747.  
  2748.  
  2749.  /* -------------------------------------------------------------------------------------- */
  2750.  
  2751.  void list_index_file(indexfilename2,savesetname2)
  2752.    char *indexfilename2;
  2753.    char *savesetname2;
  2754.    {
  2755.  
  2756.  
  2757.      INDEX_REC_TYPE indexrec;  
  2758.      BOOLEAN rvalue = FALSE;
  2759.      
  2760.  
  2761.        /* print header */
  2762.       printf("Saveset Listing for %s \n",savesetname2);
  2763.       printf("Original Size    Compressed Size   Date   Start Block  Filename\n");
  2764.       printf("__________________________________________________________________________\n");
  2765.      
  2766.       /* loop through and get file entry and print out contents */
  2767.       /* first open up the index file for reading */
  2768.                        
  2769.        TempIndexFile = fopen(indexfilename2,"r");
  2770.            
  2771.        if (TempIndexFile == NULL)
  2772.           report_error(" Could not open temporary index file.",0,severe);
  2773.        else 
  2774.         {
  2775.           if (debug)
  2776.             {
  2777.               printf("opened for read temp index file %s \n",indexfilename2);
  2778.               fflush(stdout);
  2779.             }
  2780.  
  2781.            tempindexfileopen = TRUE;
  2782.          }
  2783.           
  2784.       do {
  2785.            rvalue = get_index_file_entry(&indexrec);
  2786.          if (rvalue)
  2787.            {
  2788.                  printf("%10d          %10d  %8s   %10d  %-s\n",
  2789.                    indexrec.original_size,
  2790.                    indexrec.compressed_size,
  2791.                     indexrec.date,
  2792.                     indexrec.start_block,
  2793.                     indexrec.fname);
  2794.                fflush(stdout);
  2795.             }
  2796.  
  2797.          } while (rvalue == TRUE);
  2798.  
  2799.       printf("\nListing Complete\n\n");
  2800.       fflush(stdout);
  2801.   }
  2802.  
  2803. /* ------------------------------------------------------------------------------------ */
  2804.  int find_saveset_element(saveset)
  2805.   char saveset[18];
  2806.  
  2807.   {
  2808.     BOOLEAN found = FALSE;
  2809.     int number = 0;
  2810.     int element_number = 0;
  2811.     int slen = strlen(saveset);
  2812.  
  2813.     for (element_number = 0; element_number < max_save_sets; element_number++)
  2814.        {
  2815.         if (strncmp(raw_tape_header.header[element_number].saveset_name,saveset,slen) == 0)
  2816.           {
  2817.             number = element_number;
  2818.             found = TRUE;
  2819.             break;
  2820.           }
  2821.         }
  2822.        if (found)
  2823.          return(number);
  2824.        else return(-1); 
  2825.  
  2826.     }
  2827.  
  2828. /* --------------------------------------------------------------------------------------*/
  2829.  void list_saveset(saveset)
  2830.    char *saveset[18];
  2831.    {
  2832.      int element_number;
  2833.      char indexfilename[400];
  2834.      
  2835.        read_tape_index();
  2836.      rewind_tape(FALSE);
  2837.      element_number = find_saveset_element(saveset);
  2838.  
  2839.      if (element_number < 0)
  2840.            {
  2841.              printf("Saveset %s Not found on the tape, use LKBACKUP -l for a listing. \n",saveset);
  2842.           fflush(stdout);
  2843.              close_tape();
  2844.              report_error(" ",0,severe);
  2845.         }
  2846.  
  2847.       /* now that we found the saveset space to the directory listing and read it */
  2848.        /* tape id 1 
  2849.           1 data 2 index 3 saveset 0
  2850.           3 data 4 index 5 saveset 1
  2851.           5 data 6 index 7 saveset 2
  2852.           7 data 8 index 9 saveset 3
  2853.                .
  2854.             .
  2855.             .
  2856.             tape index [filemark]
  2857.  
  2858.           etc. */
  2859.       space_filemarks((element_number * 2) + 2);
  2860.       /* now recreate the file and list it */
  2861.       restore_file(indexfilename,0,0,TRUE);
  2862.      
  2863.       list_index_file(indexfilename,saveset);
  2864.       DeleteFile(indexfilename);
  2865.  
  2866.       rewind_tape(TRUE);
  2867.       close_tape();
  2868.  
  2869.     }
  2870.    
  2871.    /* --------------------------------------------------------------------------------- */
  2872.  void process_restore(indexfilename2,search_string)
  2873.    char *indexfilename2;
  2874.    char search_string[];
  2875.   
  2876.   {
  2877.    
  2878.    /* now go through each line in the index file and check if name matches */
  2879.    
  2880.         int lsize;
  2881.      int csize;
  2882.      int sblock;
  2883.      char ldate[9];
  2884.      char fname[351];
  2885.      int rvalue;
  2886.      BOOLEAN eof_found = FALSE;
  2887.      INDEX_REC_TYPE indexrec;
  2888.  
  2889.  
  2890.        /* first open up the index file for reading */
  2891.                        
  2892.        TempIndexFile = fopen(indexfilename2,"r");
  2893.            
  2894.        if (TempIndexFile == NULL)
  2895.           report_error(" Could not open temporary index file.",0,severe);
  2896.        else 
  2897.         {
  2898.           if (debug)
  2899.             {
  2900.               printf("opened for read temp index file %s \n",indexfilename2);
  2901.               fflush(stdout);
  2902.             }
  2903.  
  2904.            tempindexfileopen = TRUE;
  2905.          }
  2906.        
  2907.     do {
  2908.  
  2909.       rvalue = fscanf(TempIndexFile,"%350s %10d %10d %8s %10d \n",fname,&lsize,&csize,ldate,&sblock);
  2910.       if (rvalue == 0)
  2911.          report_error("Reading index file entry \n",0,severe);
  2912.  
  2913.       if (rvalue == EOF)
  2914.         {
  2915.          if (debug)
  2916.            {
  2917.              printf("EOF of index file found \n");
  2918.              fflush(stdout);
  2919.             }
  2920.           fclose(TempIndexFile);
  2921.           eof_found = TRUE;
  2922.          }
  2923.        else
  2924.         {
  2925.           if (debug)
  2926.            {
  2927.           printf("Successfully retrieved index entry %s %d %d %8s %d\n",fname,lsize,csize,ldate,sblock);
  2928.           fflush(stdout);
  2929.            }
  2930.  
  2931.      /* fill in fields */
  2932.      indexrec.original_size = lsize;
  2933.      indexrec.compressed_size = csize;
  2934.      strcpy(indexrec.fname,fname);
  2935.      strcpy(indexrec.date,ldate);
  2936.      indexrec.start_block = sblock;
  2937.  
  2938.        if (debug)
  2939.         {
  2940.           printf("Successfully filled in index entry %s %d %d %8s %d\n",
  2941.           indexrec.fname,
  2942.           indexrec.original_size,
  2943.           indexrec.compressed_size,
  2944.           indexrec.date,
  2945.           indexrec.start_block);
  2946.           fflush(stdout);
  2947.         }
  2948.       /* now check for match */
  2949.  
  2950.       if (wild_match(search_string,indexrec.fname))
  2951.          {
  2952.            if (debug)
  2953.              {
  2954.                printf("match found %s with %s \n",search_string,indexrec.fname);
  2955.                printf("current block = %d need to be at block %d \n",current_tape_block_number,
  2956.                        indexrec.start_block);
  2957.                fflush(stdout);
  2958.              }
  2959.             if (current_tape_block_number < indexrec.start_block)
  2960.               {
  2961.                 if (debug)
  2962.                   {
  2963.                   printf("attempting to space forward %d blocks \n",
  2964.                    indexrec.start_block - current_tape_block_number);
  2965.                   fflush(stdout);
  2966.                   }
  2967.                  space_scsi_blocks(indexrec.start_block - current_tape_block_number);
  2968.                  current_tape_block_number = indexrec.start_block;
  2969.                }
  2970.              else if (current_tape_block_number > indexrec.start_block)
  2971.                 {
  2972.                   /* error condition */
  2973.                   printf("TapeIO --->: Error tape position of %d > start block of %d shouldn't happen \n",
  2974.                              current_tape_block_number,indexrec.start_block);
  2975.                   fflush(stdout);
  2976.                   report_error(" ",0,severe);
  2977.                 }
  2978.                /* now restore the file */
  2979.                restore_file(indexrec.fname,indexrec.original_size,indexrec.compressed_size,FALSE);
  2980.           
  2981.            } /* end of ok match */
  2982.  
  2983.       } /* eof not found */
  2984.  
  2985.     } while (!eof_found);
  2986.  
  2987.   }   
  2988.   /* --------------------------------------------------------------------------------------*/
  2989.  
  2990.  void do_restore(saveset,search_string)
  2991.    char saveset[18];
  2992.    char search_string[];
  2993.    {
  2994.      int element_number;
  2995.      char indexfilename[400];
  2996.      
  2997.      total_bytes_read = 0;
  2998.      filescompressed = 0;
  2999.      filesuncompressed = 0;
  3000.  
  3001.      store_start_time();
  3002.      read_tape_index();
  3003.      rewind_tape(FALSE);
  3004.      element_number = find_saveset_element(saveset);
  3005.  
  3006.      if (element_number < 0)
  3007.            {
  3008.              printf("Saveset %s Not found on the tape, use LKBACKUP -l for a listing. \n",saveset);
  3009.           fflush(stdout);
  3010.              close_tape();
  3011.              report_error(" ",0,severe);
  3012.         }
  3013.  
  3014.       /* now that we found the saveset space to the directory listing and read it */
  3015.        /* tape id 1 
  3016.           1 data 2 index 3 saveset 0
  3017.           3 data 4 index 5 saveset 1
  3018.           5 data 6 index 7 saveset 2
  3019.           7 data 8 index 9 saveset 3
  3020.                .
  3021.             .
  3022.             .
  3023.             tape index [filemark]
  3024.  
  3025.           etc. */
  3026.       space_filemarks((element_number * 2) + 2);
  3027.       /* now recreate the file and list it */
  3028.       restore_file(indexfilename,0,0,TRUE);
  3029.  
  3030.       /* now position to the backup set */
  3031.       rewind_tape(FALSE);
  3032.       space_filemarks((element_number * 2) + 1);
  3033.       current_tape_block_number = 0;
  3034.        
  3035.       /* now process the restore */
  3036.       total_bytes_read = 0;
  3037.       filescompressed = 0;
  3038.       filesuncompressed = 0;
  3039.  
  3040.       process_restore(indexfilename,search_string);
  3041.       
  3042.       /* now finish up */
  3043.       DeleteFile(indexfilename);
  3044.  
  3045.       rewind_tape(TRUE);
  3046.       close_tape();
  3047.  
  3048.       if ((filescompressed+filesuncompressed) <= 0)
  3049.         {
  3050.          printf("Warning no files in saveset %s found with search string %s \n",saveset,
  3051.                  search_string);
  3052.          fflush(stdout);
  3053.         }
  3054.       else print_restore_stats();
  3055.  
  3056.     }
  3057.  
  3058. /* ------------------------------------------------------------------------------------ */
  3059.  
  3060. void do_backup(saveset_name,search_string,do_subdirs)
  3061.   char saveset_name[];
  3062.   char search_string[];
  3063.   BOOLEAN do_subdirs;
  3064.   {
  3065.     int free_element = 0;
  3066.     int taken_element = 0;
  3067.     DWORD dwThreadId;
  3068.     
  3069.     read_tape_index();
  3070.     rewind_tape(FALSE);
  3071.  
  3072.     free_element = find_free_saveset_element();
  3073.     if (free_element < 0)
  3074.       report_error("No room for any more savesets on tape, initialize it or switch tapes \n",0,severe);
  3075.     
  3076.      taken_element = find_saveset_element(saveset_name);
  3077.      if (taken_element >= 0)
  3078.            {
  3079.              printf("Error: Saveset %s Already exists on the tape... Try another name. \n",saveset_name);
  3080.           fflush(stdout);
  3081.              report_error(" ",0,severe);
  3082.         }
  3083.     else
  3084.       {
  3085.         store_start_time();
  3086.         /* now space to the correct file mark and start writing the backup */
  3087.            space_filemarks((free_element * 2) + 1 ); // 1 extra to get over header */
  3088.             /* reset the current tape block number to be relative from the beginning of the
  3089.               save set */
  3090.             current_tape_block_number = 0;
  3091.  
  3092.             /* this should put the tape ready to write the backup since there is two file marks
  3093.             per backup 1 before the backup and 1 between the backup and its directory so the
  3094.             directory can be retrieved quickly ie element 0 is filemark 0 element4 is file mark
  3095.             8 */
  3096.          
  3097.         /* now do the backup */
  3098.         total_original_size   = 0;
  3099.         total_backup_size = 0;
  3100.         filescompressed = 0;
  3101.         filesuncompressed = 0;
  3102.         processed_all_files = FALSE;
  3103.  
  3104.         /* initialize critical sections */
  3105.         InitializeCriticalSection(&Protected_Element);
  3106.         InitializeCriticalSection(&Protected_Queue);
  3107.         /* set globals here */
  3108.         global_process_subdirs = do_subdirs;
  3109.         strcpy(Global_SearchString,search_string);
  3110.          
  3111.         /* spawn a thread to process process_write_directory and go on here 
  3112.            to call mt_backup_files */
  3113.            hThread = CreateThread(NULL,0,
  3114.                          (LPTHREAD_START_ROUTINE)mt_process_write_directory,
  3115.                          (LPVOID)filesuncompressed,0,&dwThreadId);
  3116.            
  3117.            if (hThread == NULL)
  3118.              {
  3119.               printf("ERROR: child thread for compression failed to start \n");
  3120.               printf("       error code = %d \n",GetLastError());
  3121.               report_error(" ",0,severe);
  3122.              }
  3123.             else
  3124.             
  3125.              {
  3126.             
  3127.                  /* now that the thread started call the receive routine to get process
  3128.                   the compressed files */
  3129.                 thread_active = TRUE;
  3130.                 /* allow this thread to sleep to give the compress thread time to do some 
  3131.                    processing */
  3132.                 /* only sleep if doing compression */
  3133.                   if (want_compression)
  3134.                      Sleep(10000); /* ten seconds */
  3135.                 mt_backup_files();
  3136.               }
  3137.     
  3138.         
  3139.          /* close the thread handle */
  3140.          
  3141.          CloseHandle(hThread);
  3142.          thread_active = FALSE;
  3143.  
  3144.  
  3145.         /* dont write marks if nothing was backed up */
  3146.         if ((filescompressed + filesuncompressed) == 0)
  3147.            {
  3148.              printf("Warning no files found in search parameter %s \n",search_string);
  3149.              fflush(stdout);
  3150.            }
  3151.         else
  3152.            {
  3153.               /* now write the file mark */
  3154.              write_filemarks(1);
  3155.              /* now write the directory file */
  3156.              write_directory_file();
  3157.              /* now write another file mark */
  3158.              write_filemarks(1);
  3159.  
  3160.             /* now fill in the total size/compressed size and rewind and rewrite header */
  3161.             /* also print out status messages */
  3162.             fill_in_header_element(saveset_name,total_original_size,total_backup_size,
  3163.                     todays_date,free_element);
  3164.             /* now rewrite header */
  3165.             write_tape_index(TRUE);
  3166.            }
  3167.         
  3168.         /* now rewind tape */
  3169.         rewind_tape(TRUE);
  3170.         close_tape();
  3171.         print_backup_stats();
  3172.  
  3173.    } /* is room for new saveset */
  3174.  }
  3175.  
  3176. /* ------------------------------------------------------------------------------------ */
  3177.  void disp_help()
  3178.    {
  3179.      printf("             USAGE for LKBACKUP Version 1.0 by L. Kahn 1993           \n");
  3180.      printf("LKBACKUP [-d -q -c -s] -b saveset_name search_string [include_subdirs] \n");
  3181.      printf("LKBACKUP [-d -q -c] -e [long_or_short] or LGKBACKUP -h or    \n");
  3182.      printf("LKBACKUP [-d -q -c -s] -i or\n");
  3183.      printf("LKBACKUP [-d -q -c -s] -L saveset_name or\n");  
  3184.      printf("LKBACKUP [-d -q -c -s] -l or                \n");
  3185.      printf("LKBACKUP [-d -q -c -s] -r saveset_name search_string \n");
  3186.      printf("LKBACKUP [-d -q -c -s] -C no_of_good_savesets\n");
  3187.      printf("-b = Backup using the search string starting from the current directory, \n"); 
  3188.      printf("     including subdirs is optional and depedent on the value of \n");
  3189.      printf("     include_subddirs (t or f) \n");
  3190.      printf("-e = Erase tape where erasing long or short is optional. Default is short \n");
  3191.      printf("-h = Display this HELP message \n");
  3192.      printf("-i = Initialize tape (necessary before usage) \n");
  3193.      printf("-l = List tape (i.e., name of all savesets)\n");
  3194.      printf("-L = List the contents of a specific saveset \n"); 
  3195.      printf("-r = Restore the saveset_name using the search_string\n");
  3196.      printf("-C = Catalog tape (set index to say there are no_good_savesets) \n");
  3197.      printf("     Should be used if for some reason a backup fails or power goes out\n");
  3198.      printf("     during a backup. Rewrites the tape index, restores can then be \n");
  3199.      printf("     performed but further backups may be unreliable.\n");
  3200.      printf("-d = debug main, -q = quiet_mode, -D debug thread, -B debug both,\n"); 
  3201.      printf("-c = turn comprssion on, -s use setmarks not filemarks");
  3202.    
  3203.  }
  3204.  
  3205. /* ------------------------- main program */
  3206.   
  3207.   void main(int argc,char *argv[])
  3208.   { 
  3209.   
  3210.       int current_arg = 1;
  3211.       BOOLEAN more_args = TRUE;
  3212.       BOOLEAN done = FALSE;
  3213.       BOOLEAN do_subdirs = FALSE;
  3214.  
  3215.        file_mapping = FALSE;
  3216.        want_compression = FALSE; /* this also does not speed things up and uses more tape 
  3217.                                      since the drive cannot keep streaming */
  3218.      
  3219.        fill_in_todays_date();
  3220.        if ((argc < 2) || (argc > 8)) 
  3221.          disp_help();
  3222.        else
  3223.          
  3224.          {
  3225.            /* process arguments */
  3226.             if (argv[current_arg][0] != '-')
  3227.               disp_help();
  3228.            else
  3229.         
  3230.             do 
  3231.               {
  3232.            /* get the first one and if it doesn't start with a - we have a problem */
  3233.         
  3234.               switch (argv[current_arg][1])
  3235.                 {
  3236.                 case 'q':
  3237.                   quiet_mode = TRUE;
  3238.                   break;
  3239.                   
  3240.                   case 'c':
  3241.                   want_compression = TRUE;
  3242.                   break;
  3243.  
  3244.                 /* undocumented default is no file mapping since this does not seem to speed
  3245.                    things up */    
  3246.                 case 'm':
  3247.                   file_mapping = TRUE;
  3248.                   break;
  3249.                 
  3250.                 case 'd':
  3251.                   debug = TRUE;
  3252.                   break;
  3253.                 
  3254.                 case 'D':
  3255.                   debug_child = TRUE;
  3256.                   break;
  3257.                  
  3258.                 case 'B':
  3259.                    debug_child = TRUE;
  3260.                    debug = TRUE;
  3261.                    break;
  3262.  
  3263.                 case 'h':
  3264.                   disp_help();
  3265.                   done = TRUE;
  3266.                   break;
  3267.  
  3268.                  case 's':
  3269.                    set_mark_positioning = TRUE;
  3270.                    break;
  3271.  
  3272.                   case 'C':
  3273.                   if (argc < (current_arg + 2))
  3274.                     {
  3275.                      printf("ERROR: Number of good savesets needed for catalog procedure \n");
  3276.                      fflush(stdout);
  3277.                     }
  3278.                    else {
  3279.                          catalog_tape(argv[current_arg + 1]);
  3280.                           }
  3281.  
  3282.                    done = TRUE;
  3283.                    break;
  3284.             
  3285.                 case 'i':
  3286.                    initialize_tape();
  3287.                    done = TRUE;
  3288.                    break;
  3289.                 
  3290.                 case 'l':
  3291.                    list_tape();
  3292.                    done = TRUE;
  3293.                    break;
  3294.                 
  3295.                 case 'L':
  3296.                   if (argc < (current_arg + 2))
  3297.                     {
  3298.                      printf("ERROR: Saveset name needed for tape listing. Use LKBACKUP -h for help \n");
  3299.                      fflush(stdout);
  3300.                     }
  3301.                    else {
  3302.                          list_saveset(argv[current_arg + 1]);
  3303.                           }
  3304.  
  3305.                    done = TRUE;
  3306.                    break;
  3307.                  
  3308.                  case 'e':
  3309.                      if (argc >= (current_arg + 2))
  3310.                       {
  3311.                      /* we have a short or long option so check it */
  3312.                      switch (argv[current_arg+1][0])
  3313.                        {
  3314.                          case 's':
  3315.                           erase_tape(FALSE);
  3316.                           done = TRUE;
  3317.                           break;
  3318.  
  3319.                          case 'l':
  3320.                            erase_tape(TRUE);
  3321.                            done = TRUE;
  3322.                            break;
  3323.                          
  3324.                          default:
  3325.                           printf("ERROR: Legal options for erase are s for short erase or l for long erase \n");
  3326.                           printf("Use LKBACKUP -h for help \n");
  3327.                           fflush(stdout);
  3328.                           done = TRUE;
  3329.                           break;
  3330.                          }
  3331.                          if (done)
  3332.                            break;
  3333.                         } /* end have extra arg */
  3334.  
  3335.                       else erase_tape(FALSE);
  3336.                      done = TRUE;
  3337.                      break;
  3338.   
  3339.                  case 'b':
  3340.                      /* make sure we have enough parms */
  3341.                      if (argc < (current_arg+3)) 
  3342.                          {
  3343.                           printf("ERROR: The search_string and the saveset_name are required for a backup operation. \n");
  3344.                           printf("Use LKBACKUP -h for help \n");
  3345.                           fflush(stdout);
  3346.                           done = TRUE;
  3347.                           break;
  3348.                          }
  3349.  
  3350.                       /* check for include subdirs */
  3351.                     if (argc == (current_arg + 4))
  3352.                        {
  3353.                        
  3354.                        switch (argv[current_arg+3][0])
  3355.                          {
  3356.                           case 't': 
  3357.                             do_subdirs = TRUE;
  3358.                             break;
  3359.                           case 'f':
  3360.                             do_subdirs = FALSE;
  3361.                             break;
  3362.                           default:
  3363.                              printf("Error: The legal options for including subdirectories are t for f.\n");
  3364.                             printf("Use LKBACKUP -h for help \n");
  3365.                             fflush(stdout);
  3366.                             done = TRUE;
  3367.                             break;
  3368.                           }
  3369.                        } /* have optional parm */
  3370.                       if (done)
  3371.                         break;
  3372.  
  3373.                      /* if we get here do the backup */
  3374.                      if (debug)
  3375.                        {
  3376.                         printf("calling backup %s %s %d \n",argv[current_arg+1],
  3377.                                   argv[current_arg+2],do_subdirs);
  3378.                         fflush(stdout);
  3379.                         }
  3380.                        do_backup(argv[current_arg+1],argv[current_arg+2],do_subdirs);
  3381.                        done = TRUE;
  3382.                        break;
  3383.  
  3384.                  case 'r':
  3385.                                    /* make sure we have enough parms */
  3386.                      if (argc < (current_arg+3)) 
  3387.                          {
  3388.                           printf("ERROR: The search_string and the saveset_name are required for a restore operation. \n");                          printf("Use LKBACKUP -h for help \n");
  3389.                           fflush(stdout);
  3390.                           done = TRUE;
  3391.                           break;
  3392.                          }
  3393.                        
  3394.                        else
  3395.                         {
  3396.                           if (debug)
  3397.                             {
  3398.                              printf("Restore %s %s \n",argv[current_arg+1],argv[current_arg+2]);
  3399.                              fflush(stdout);
  3400.                             }
  3401.  
  3402.                          do_restore(argv[current_arg+1],argv[current_arg+2]);
  3403.                          done = TRUE;
  3404.                          break;
  3405.                         }
  3406.  
  3407.                  default:
  3408.                   printf("Illegal option %s \n",argv[current_arg]);
  3409.                   disp_help();
  3410.                   done = TRUE;
  3411.                   break;
  3412.  
  3413.                 } /* end of switch */
  3414.                
  3415.                ++current_arg;
  3416.                if (current_arg > argc)
  3417.                  more_args = FALSE;
  3418.                    
  3419.               } while ((!done) && (more_args));
  3420.  
  3421.     } /* end of ok case */    
  3422.   } /* end of main */
  3423.                    
  3424.  
  3425.   
  3426.